python面向对象编程:魔方法和内置属性

__init__(self)

是初始化方法,初始化实例的时候自动调用,方法有一个参数 self,代表当前创建的实例对象。__init__方法在 __new__方法的基础上完成一些初始化工作,不需要返回值。

__new__(cls)

是一个静态方法,当实例化一个类对象时,最先被调用的是__new__ 方法。该方法第一个参数 cls 表示当前要实例化的类。__new__方法必须要有返回值,是实例化对象(即self传给__init__方法),__new__()使用场景:
1、单例模式

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        # 实例化类的时候,可以用于确保一个类只有一个实例存在
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

2、继承一些不可变的类时

class absint(int):
    # 取整数绝对值
    def __new__(cls, value):
        return super().__new__(cls, abs(value))


a = absint(-1)
print(a)
__del__(self)

在实例将被销毁时调用。del x 并不直接调用 x.__del__(),前者会将 x 的引用计数减一,而后者仅会在 x 的引用计数变为零时被调用。

__repr__(self)

由 repr() 内置函数调用以用于返回一个对象的字符串表示形式。这个方法返回的字符串应该能够用来重新创建这个对象。

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

    def __repr__(self):
        return f"Animal(name={self.name}, age={self.age})"


obj = Animal('Tugou', 2)

# 打印对象的字符串表示形式
print(obj)
# Animal(name=Tugou, age=2)
__str__(self)

通过 str(object) 用于返回一个对象的字符串表示形式。当使用 print() 或 str() 函数时Python 会调用该对象的__str__() 方法来获取字符串表示。

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

    def __str__(self):
        return f"{self.name}, {self.age} 岁"


person = Person("Alice", 25)

# 打印对象的字符串表示形式
print(person)
# Alice, 25 岁

命令行中二者的区别

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

    def __str__(self):
        return f"{self.name}, {self.age} 岁"

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"
    # 创建一个 Person 对象



person = Person("Alice", 25)
# 命令行调用
person
Person(name=Alice, age=25)
# 命令行使用print打印
print(person)
Alice, 25
__lt__(self, other)
x<y 调用 x.__lt__(y)
__le__(self, other)
x<=y 调用 x.__le__(y)
__eq__(self, other)
x==y 调用 x.__eq__(y)
__ne__(self, other)
x!=y 调用 x.__ne__(y)
__gt__(self, other)
x>y 调用 x.__gt__(y)
__ge__(self, other)
x>=y 调用 x.__ge__(y)
__hash__(self)

通过内置函数 hash() 调用以对哈希集的成员进行操作,如果一个类没有定义__eq__() 方法,那么也不应该定义__hash__() 操作

__getattr__(self, name)

访问不存的属性时调用,也就是引发 AttributeError 而失败时被调用。

__getattribute__(self, name)

此方法会无条件地被调用以实现对类实例属性的访问,也就是每当尝试访问一个对象的属性时,都会自动调用__getattribute__方法。如果类还定义了__getattr__(),则后者不会被调用,除非__getattribute__() 显式地调用它或是引发了 AttributeError。

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

    def __getattr__(self, item):
        '''
            访问不存的属性时调用,
        '''
        try:
            print('{} {} in __getattr__ method'.format(self, item))
            return object.__getattribute__(self, item)
        except:
            return 'Not find attribute: {}'.format(item)

    def __getattribute__(self, item):
        '''
            访问存在的属性,如果访问属性不存在的时候随后会调用__getattr__
        '''
        print('{} {} in __getattribute__ method'.format(self, item))
        return object.__getattribute__(self, item)


person = Person("Alice", 25)

person.sex
print(person.name)
<__main__.Person object at 0x00000000024FCDC8> sex in __getattribute__ method
<__main__.Person object at 0x00000000024FCDC8> sex in __getattr__ method
<__main__.Person object at 0x00000000024FCDC8> name in __getattribute__ method
Alice
__setattr__(self, name, value)

此方法在一个属性被尝试赋值时被调用。name 为属性名称, value 为要赋给属性的值。

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

    def __setattr__(self, key, value):
        '''
            设置属性,初始化的时候也要调用该方法
        '''
        print('{} {} in __setattr__ method'.format(self, key))
        object.__setattr__(self, key, value)

person = Person("Alice", 25)

person.sex = "man"
print(person.sex)

<__main__.Person object at 0x0000000001F2CC08> name in __setattr__ method
<__main__.Person object at 0x0000000001F2CC08> age in __setattr__ method
<__main__.Person object at 0x0000000001F2CC08> sex in __setattr__ method
man
__call__()

允许将对象像函数一样进行调用。当一个对象实现了__call__ 方法时,您可以像调用函数一样调用该对象,即使用括号运算符 () 来调用它

class MyCallable:
    def __call__(self, x, y):
        return x + y

# 创建一个可调用的对象
my_callable = MyCallable()

# 调用对象,就像调用函数一样
result = my_callable(3, 5)
print(result)  # 输出: 8
__contains__(self, item)

方法用于检查对象是否包含某个元素,通常在使用 in 运算符时自动调用。

class MyList:
    def __init__(self, data):
        self.data = data

    def __contains__(self, item):
        return item in self.data

lst = MyList([1, 2, 3, 4, 5])
print(3 in lst)  # 输出: True
__iter__(self)

用于定义该类的实例是可迭代对象,并且应该返回一个迭代器。当自定义类需要支持迭代时,就需要在类中定义__iter__() 方法。

class myiterable:
    data = [0, 1, 2, 3]

    def __iter__(self):
        return self.data


mi = myiterable()
res = isinstance(mi, Iterable)  # True 是可迭代对象
print(res)
__getitem__(self, key)

用于实现通过 obj[key] 来访问对象的方法,并且支持整数索引和切片。

# requests/structures.py CaseInsensitiveDict LookupDict 实现了__getitem__
# requests/cookies.py RequestsCookieJar 
from sortedcontainers.sorteddict import SortedDict

sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
siv = sd.items()

from collections.abc import Iterator  # 迭代器
from collections.abc import Iterable  # 可迭代对象


class DataSequence:
    def __init__(self):
        self.data = [1, 2, 3, 4, 5]

    def __getitem__(self, index):
        return self.data[index]

    def __len__(self):
        return len(self.data)

    # def __iter__(self):
    #     return iter(self.data)


ds = DataSequence()
print(isinstance(ds, Iterable))
print(isinstance(ds, Iterator))

# 因为 for 循环会尝试按索引从 0 开始访问序列元素
for i in ds:
    print(i)


__slots__

这个特性可以限制类的属性,只能给类赋值__slots__里的属性,该属性不会对子类生效。类在定义的时候会根据__slots__定义的属性,来分配内存大小,从而节省空间。会阻止自动为每个实例创建__dict__ 和__weakref__。

class Student:
    __slots__ = 'name', 'age', 'score'

    def __init__(self, name, age):
        self.name = name
        self.age = age
s.score = 99
s.sex = "male"
# 给sex赋值的时候会报错,因为__slots__里面没有sex属性
# AttributeError: 'Student' object has no attribute 'sex'
__dict__

字典形式,列出类或对象的所有属性和属性值。

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

Student.__dict__
# 包含所有类属性
{
    '__module__': '__main__', 
    '__init__': <function Student.__init__ at 0x000001B86E44A168>, 
	'__dict__': <attribute '__dict__' of 'Student' objects>, 
	'__weakref__': <attribute '__weakref__' of 'Student' objects>, 
	'__doc__': None
}
s = Student('burus', 15)
s.__dict__
# 包含实例的属性
{
	'name': 'zhangliang', 
 	'age': 33
}
__class__

返回当前实例属于哪个类。

__base__

如果继承了多个类, 那么只显示继承的第一个类, 没有显示继承则返回object

__bases__

返回一个元组, 会显示所有直接继承的父类, 如果没有显示的继承, 则返回(object,)

__mro__

mro表示Method Resolution Order, 表示方法查找顺序, 会从自身除法, 找到最顶层的父类, 因此返回自身、继承的基类、以及基类继承的基类, 一直找到object

class A:
    pass


class B:
    pass


class C(A, B):
    pass


class D(C):
    pass


d = D()
print(d.__class__)
<class '__main__.D'>
print(C.__bases__)
(<class '__main__.A'>, <class '__main__.B'>)
print(D.__base__)
<class '__main__.C'>
print(D.__mro__)
(<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

你可能感兴趣的:(Python,python)