一、跟实例创建和执行有关的

  __new__、__init__、__call__.

  类加括号调用了__init__方法来创建一个实例对象。这一过程分成了两步: 类调用__new__来创建实例对象,__new__调用__init__来初始化实例对象。

class A:
    count = 0
    def __init__(self):
        print("__init__ has called. 2")
       
    def __new__(cls):
        print("__new__ has called. 1")
        return object.__new__(cls)
    def __call__(cls):
        print("__call__ has called. 3")
a = A()
a()

"""
__new__ has called. 1
__init__ has called. 2
__call__ has called. 3
"""

  类的__new__()方法很少通过用户代码定义。如果定义了它,它通常是用原型__new__(cls, *args, **kwargs)编写的。其中args和kwargs与传递给__init__()的参数相同。__new__()始终是一个类方法,接受类对象作为第一个参数。尽管__new__()会创建一个实例,但它不会自动地调用__init__()。实例对象加括号会调用__call__方法,一般作为程序的入口,并且可以在这一步修改实例属性或调用实例方法。

class Obj(object):
    def __init__(self, name, price):
        self.name = name
        self.__price = price

    def __say(self):
        print("{}, {}.".format(self.name, self.__price))

    def __call__(self, discount):
        self.__price = discount * self.__price
        self.__say()


apple = Obj("apple", 10.0)
apple(0.8)

二、跟实例属性有关的

  __getattribute__,  __getattr__,  __setattr__, __delattr__、__getitem__、__setitem__、__delitem__、__missing__

  在__init__时,会调用__setattr__初始化实例属性,在__dict__添加键值对。

 

class Sample:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __setattr__(self, key, value):
        print("__setattr__ has called.")
        try:
            self.__dict__[key] = value
        except:
            self.__dict__ = {key: value}

sam = Sample("Li", 24)

# __setattr__ has called.
# __setattr__ has called.

 

  对实例属性的访问时,

  1.首先执行__getattribute__方法(这又是一个特殊方法),去调用object基类的__getattribute__来查询__dict__里的键值对。如果存在则直接返回,相当于执行了member.__dict__.get(obj),如果不存在则调用__getattr__方法。

  2.__getattr__方法会在实例内存空间中尽可能的搜索该属性值,如果搜索到则直接返回,搜索不到会抛出AttributeError。

  注意下面两段代码的区别:__getattribute__的return只是一个硬编码的字符串而不是属性值,__getattr__的return则是实例的属性值。因此,如果有需求,一般会在__getattr__里写需求代码。

 

 

class MemberCounter:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __getattribute__(self, obj):
        print("__getattribute__ is called.")
        return object.__getattribute__(self, obj)
    
    def __getattr__(self, obj):
        print("__getattr__ is called.")
        return "{} Not assgined.".format(obj)
member = MemberCounter("An", 24)

print(member.name)
print("\n------------------\n")
print(member.gender)

"""
__getattribute__ is called.
An

------------------

__getattribute__ is called.
__getattr__ is called.
gender Not assgined.
"""

 

class MemberCounter:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __getattribute__(self, obj):
        if obj == "gender":
            return "male"
        else:
            return object.__getattribute__(self, obj)

member = MemberCounter("An", 24)
print(member.gender)
member.gender = "female"
print(member.gender)
print(member.__dict__)
 
"""
male
male
{'name': 'An', 'age': 24, 'gender': 'female'}
"""
__getattribute__

相关文章:

  • 2021-12-12
  • 2021-06-25
  • 2021-07-06
  • 2021-07-29
  • 2021-09-23
  • 2022-12-23
  • 2022-01-06
  • 2022-12-23
猜你喜欢
  • 2021-11-23
  • 2021-10-28
  • 2022-12-23
  • 2022-12-23
  • 2022-01-25
  • 2022-12-23
  • 2022-02-27
相关资源
相似解决方案