欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python语法基础学习笔记Task11:魔法方法

程序员文章站 2024-03-15 22:56:24
...

1、python的魔法方法

魔法方法是指Python内部已经包含的,被双下划线所包围的方法,这些方法在进行特定的操作时会自动被调用,它们是Python面向对象下智慧的结晶

2、关于属性的魔法方法

  • __ getattribute __(self, name)----定义了属性被访问时的行为,而__getattr__只有该属性不存在时才会起作用,因此,在支持__getattribute__的Python版本,调用__getattr__前必定会调用 __ getattribute __,调用时应注意避免"无限递归"的错误。
  • __ getattr __(self, name)----该方法定义了你试图访问一个不存在的属性时的行为。因此,重载该方法可以实现捕获错误拼写然后进行重定向, 或者对一些废弃的属性进行警告。
  • __ setattr __(self, name, value)----是实现封装的解决方案,它定义了你对属性进行赋值和修改操作时的行为。不管对象的某个属性是否存在,它都允许你为该属性进行赋值,因此你可以为属性的值进行自定义操作,但是要注意避免"无限递归"的错误。
  • __ delattr __(self, name)----定义的是删除属性时的行为,调用时注意避免"无限递归"的错误。
classAccess(object):

    def__getattr__(self, name):
        print '__getattr__'
        return super(Access, self).__getattr__(name)

    def__setattr__(self, name, value):
        print '__setattr__'
        return super(Access, self).__setattr__(name, value)

    def__delattr__(self, name):
        print '__delattr__'
        return super(Access, self).__delattr__(name)

    def__getattribute__(self, name):
        print '__getattribute__'
        return super(Access, self).__getattribute__(name)

access = Access()
access.attr1 = True  # __setattr__调用
access.attr1  # 属性存在,只有__getattribute__调用
try:
    access.attr2  # 属性不存在, 先调用__getattribute__, 后调用__getattr__
except AttributeError:
    pass
del access.attr1  # __delattr__调用
  • 无限递归错误
# 以上例子都是,每一次属性赋值时, 方法都会被调用,因此不断调用自身导致无限递归了
def __setattr__(self, name, value):
    self.name = value

def __getattribute__(self, item):
    print('__getattribute__')
    return self.item

def __getattribute__(self, name):
    return self.__dict__[name]

# 正确的写法
def __setattr__(self, name, value):
    self.__dict__[name] = value
    
def __getattribute__(self, item):
    print('__getattribute__')
    return super().__getattribute__(self, item)

3、实例对象属性寻找的顺序

  • 首先访问 __ getattribute __() 魔法方法(隐含默认调用,无论何种情况,均会调用此方法)。
  • 接着,去t.__dict__中查找是否具备该属性。
  • 若在 t.__ dict __ 中找不到对应的属性, 则去t.__ class __.__dict__中寻找。
  • 若在实例的类中也找不到该属性,则去父类中寻找,即 t.__ class . bases __.__dict__中寻找。
  • 若以上均无法找到,则会调用 __ getattr __ 方法,执行内部的命令(若未重载 __ getattr __ 方法,则直接报错:AttributeError)
class Test:
    def __getattr__(self, item):
        print('__getattr__')

    def __getattribute__(self, item):
        print('__getattribute__')
        #super().__getattribute__(item)
        #object.__getattribute__(self,item)

    def __setattr__(self, item, value):
        print('__setattr__')

    def __delattr__(self, item):
        print('__delattr__')

t = Test()
t.x
#__getarrtribute__

以上这个程序在访问一个不存在的属性的时候并没有调用__ getattr __ ,而只是调用了__ getatrrribute __ 。这个的问题就出在了步骤的第④步,因为,一旦重载了 __ getattribute __ () 方法,如果找不到属性,则必须要手动加入第④步,否则是无法进入到 第⑤步 (__ getattr __)的。

  • 方法一:采用 object(所有类的基类)
class Test:#父类
    def __getattr__(self, item):
        print('__getattr__')

    def __getattribute__(self, item):
        print('__getattribute__')
        #super().__getattribute__(item)
        object.__getattribute__(self,item)

    def __setattr__(self, item, value):
        print('__setattr__')

    def __delattr__(self, item):
        print('__delattr__')

t = Test()
t.x
#__getattribute__
#__getattr__
  • 方法二:采用 super() 方法
class Test:#父类
    def __getattr__(self, item):
        print('__getattr__')

    def __getattribute__(self, item):
        print('__getattribute__')
        super().__getattribute__(item)
        #object.__getattribute__(self,item)

    def __setattr__(self, item, value):
        print('__setattr__')

    def __delattr__(self, item):
        print('__delattr__')

t = Test()
t.x
#__getattribute__
#__getattr__

4、一些基础魔法方法
python语法基础学习笔记Task11:魔法方法
5、属性相关的方法
python语法基础学习笔记Task11:魔法方法
6、比较操作符
python语法基础学习笔记Task11:魔法方法
7、算数运算符
python语法基础学习笔记Task11:魔法方法
参考文献

  • https://blog.csdn.net/LSGO_MYP/article/details/102573292
  • https://blog.csdn.net/qq_38520096/article/details/79237593
  • https://www.cnblogs.com/zhouyixian/p/11129347.html
  • https://www.cnblogs.com/blackmatrix/p/5681480.html