__getattr__和__getattribute__的区别

__ getattr __

当你请求获取一个并没有定义的属性时,python将会调用此方法。下图示例当中,Count没有__ getattr __方法,我们获取obj1.mymin和obj2.mymax这两个参数都可以成功获取,但是当我们尝试得到obj1.mycurrent参数时,python抛出了属性异常AttributeError: 'Count' object has no attribute 'mycurrent'’

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

我们给Count类加上__ getattr __方法

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

虽然obj1.mycurrent1属性并没有定义,__ getattr __方法返回的值仍然被打印出来,

1
10
0

__ getattribute __

如果在你的类当中,存在__ getattribute __方法,Python将会为每个属性调用这个方法无论它存在与否。那我们使用 __ getattribute __ 方法的目的是?主要还是为了控制属性的访问,并且增加它们的安全性。如下图所示,任何人只要访问我以cur开头的属性,将抛出定义的异常。

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

控制台输出:

1
Traceback (most recent call last):
10
  File "/Users/stellaye/PycharmProjects/getattrmethods/属性方法对比.py", line 17, in 
    print(obj1.current)
  File "/Users/stellaye/PycharmProjects/getattrmethods/属性方法对比.py", line 10, in __getattribute__
    raise AttributeError
AttributeError

注意:
为了防止在__ getattribute __ 方法里的无限循环,它应该执行基础类的 __ getattribute __方法(同时传递要获得的属性).例如object. __ getattribute __(self, name) 或者 super(). __ getattribute __(item) 而不是 self. __ dict __[item]

总结

当你的类里面同时有 __ getattr __和 __ getattribute __ 这两个魔法方法时, __ getattribute __方法将会首先被调用.但是如果 __ getattribute __方法引发了AttributeError异常,那么这个异常会被忽略,取而代之 __ getattr __方法被调用。

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

输出

1
10
0

你可能感兴趣的:(__getattr__和__getattribute__的区别)