pytho的魔术方法之属性

    xiaoxiao2022-07-13  148

    文章目录

    特殊属性查看属性魔术方法实例化可视化hash运算符容器相关方法可调用对象

    特殊属性

    属性说明__name __类、函数、方法等的名字,实例没有__name__的属性__module __类定义所在的模块名__class __对象或类所属的类__bases __类的基类的元组,顺序为它们在基类列表中出现的顺序__doc __类、函数的文档字符串,如果没有定义则为 None__mro __类的mro,class.mro()返回的结果的保存在 __mro ____dict __类或实例的属性,可写的字典

    `

    查看属性

    __dir __ 方法

    方法说明__dir __返回类或者对象的所有成员 名称列表。通过内建函数 dir() 操作实例就是调用 __dir __()。

    如果dir([obj])参数obj包含方法__dir__(),该方法将被调用。如果参数obj不包含__dir__(),该方法将最大限度地收集属性信息。

    dir(obj)对于不同类型的对象obj具有不同的行为:

    如果对象是模块,返回的列表包含模块的属性名和变量名如果对象是类,返回的列表包含类的属性名,及它的祖先类的属性名如果是类的实例 有__dir__方法,返回可迭代对象的返回值没有__dir__方法,则尽可能收集实例的属性名、类的属性和祖先类的属性名

    如果dir([obj])中的obj不写,则分3种情况

    在模块中,返回模块的属性和变量名在函数中,返回本地作用域的变量名在方法中,返回本地作用域的变量名

    dir 方法一定要返回一个可迭代对象

    不管__dir__ 方法返回的是什么要的可迭代对象,最终都会被解释器转换为一个列表

    class Animal: def __init__(self,name): self.name = name cat = Animal('cat') print(dir(cat)) # 该方法将最大限度地收集属性信息,返回的列表包含类的属性名,及它的祖先类的属性名 ------------------------------------- ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name'] class Animal: def __init__(self,name): self.name = name def __dir__(self): return ['a','b'] #必须返回可迭代对象 cat = Animal('cat') print(dir(cat)) ------------------------------------ ['a', 'b']

    __dir __() 方法测试

    class Person: def show(self): # 方法中 a = 100 t = int(a) print(dir()) #返回变量字典,形参也是变量 print(locals()) #返回字典 def test(a=50, b=100): # 函数中 c = 150 print(dir()) print(locals()) print(globals()) Person().show() test() print(dir()) ------------------------------------------------------------------------------- ['a', 'self', 't'] {'self': <__main__.Person object at 0x000001A581F4DAC8>, 'a': 100, 't': 100} ['a', 'b', 'c'] {'a': 50, 'b': 100, 'c': 150} ['Person', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'test'] {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000220A1AE6668>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/pycharm/test/Animal.py', '__cached__': None, 'Person': <class '__main__.Person'>, 'test': <function test at 0x00000220A38F2378>}

    内建函数

    locals() 返回当前作用域中的变量字典globals() 当前模块全局变量的字典

    魔术方法

    魔术方法的分类

    创建、初始化与销毁 __new __ 、__init __ 、__del __hashbool可视化运算符重载容器和大小可调用对象上下文管理反射描述器其他杂项

    实例化

    方法意义__new __实例化一个对象,该方法需要返回一个值,如果该值不是cls的实例,则不会调用__init__该方法永远都是静态方法 class Person: def __new__(cls, *args, **kwargs): print(cls) print(args) print(kwargs) return None def __init__(self, name): self.name = name tom = Person("tom") print(tom) ---------------------------------------------------- <class '__main__.Person'> ('tom',) {} None __new__方法很少使用,即使创建了该方法,也会使用return super().new(cls)基类object的__new__方法来创建实例并返回

    可视化

    方法意义__str __str()函数、format()函数、print()函数调用,需要返回对象的字符串表达。如果没有定义,就去调用__repr__方法返回字符串表达,如果__repr__没有定义,就直接返回对象的内存地址信息__repr __内建函数repr()对一个对象获取字符串表达。调用__repr__方法返回字符串表达,如果__repr__也没有定义,就直接返回object的定义就是显示内存地址信息__bytes __bytes()函数调用,返回一个对象的bytes表达,即返回bytes对象 使用方法如下 class Person: def __init__(self, name, age=18): self.name = name self.age = age def __repr__(self): return 'repr: {},{}'.format(self.name, self.age) def __str__(self): return 'str: {},{}'.format(self.name, self.age) def __bytes__(self): return "{} is {}".format(self.name, self.age).encode() tom = Person('tom') print(tom) # print函数使用__str__ print('{}'.format(Person('tom'))) print([Person('tom')]) # []使用__str__,但其内部使用__repr__ print(tom.__dict__) ---------------------------------------------------- str: tom,18 str: tom,18 [repr: tom,18] {'name': 'tom', 'age': 18}

    hash

    方法意义__hash __内建函数hash()调用的返回值,返回一个整数。如果定义这个方法该类的实例就可hash。__eq __对应==操作符,判断2个对象是否相等,返回bool值定义了这个方法,如果不提供__hash__方法,那么实例将不可hash了 class Person: def __init__(self, name, age=18): self.name = name self.age = age def __hash__(self): return 100 A = Person('tom') tom = Person('tom') print(hash(tom),hash(A)) ##两个对象的哈希值相同,都为设定的100 print({A,tom}) ## hash 值相同,但是并不能去重 ---------------------------------------------------- 100 100 {<__main__.Person object at 0x0000014463288358>, <__main__.Person object at 0x0000014462F86710>}

    要去重,必须还要相等,如下

    class Person: def __init__(self, name, age=18): self.name = name self.age = age def __hash__(self): return 100 def __eq__(self, other): # 这个函数作用就是判断个实例是否相等,相等返回 True,不等返回 False return self.name == other.name print(hash(tom),hash(A)) ##两个对象的哈希值相同,都为设定的100 ,设为相同 print({A,tom}) # hash 值相同,并且通过__eq__判断内容相等,就会进行去重处理 ---------------------------------------------------- 100 100 {<__main__.Person object at 0x000002BA70E46710>} 去重必须要满足 hash值一样,并且内容相等
    方法意义__ bool__内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回布尔值。没有定义__bool__(),就找__len__()返回长度,非0为真。如果__len__()也没有定义,那么所有实例都返回真

    运算符

    特殊方法含义<, <=, ==, >, >=, !=__lt __, __le __, __eq __, __gt __, __ge __, __ne __比较运算符+, -, *, /, %, //, **, divmod__add __, __sub __, __mul __, __truediv __, __mod __, __floordiv __, __pow __, __divmod __算数运算符,移位、位运算也有对应的方法+=, -=, *=, /=, %=, //=, **=__iadd __, __isub __, __imul __, __itruediv __, __imod __, __ifloordiv __, __ipow __ 实现Point类的2个实例相加,减 class Point: def __init__(self,x,y): self.x = x self.y = y def __add__(self,other): return (self.x + other.x , self.y + other.y) def __sub__(self,other): return (self.x - other.x , self.y - other.y) def __str__(self): return str((self.x, self.y)) p1 = Point(2,3) p2 = Point(5,6) print(p1+p2) print(p1-p2) ------------------------------------------------------------------------ (7, 9) (-3, -3)

    __ isub __方法定义,一般会in-place就地来修改自身如果没有定义__isub__方法,则会调用__sub __

    class Person: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): # __eq__等于可以推断不等于 return self.age == other.age def __gt__(self, other): # __gt__大于可以推断小于 return self.age > other.age def __ge__(self, other): # __ge__大于等于可以推断小于等于 return self.age >= other.age tom = Person('tom', 20) jerry = Person('jerry', 16) print(tom > jerry) >>>True print(tom < jerry) >>>False print(tom >= jerry) >>>True print(tom <= jerry) >>>False print(tom == jerry) >>>False print(tom != jerry) >>>True

    容器相关方法

    方法意义__len __内建函数len(),返回对象的长度(>=0的整数),如果把对象当做容器类型看,就如同list或者dict。bool()函数调用的时候,如果没有__bool__()方法,则会看__len__()方法是否存在,存在返回非0为真__iter __迭代容器时,调用,返回一个新的迭代器对象__contains __in 成员运算符,没有实现,就调用__iter__方法遍历__getitem __实现self[key]访问。序列对象,key接受整数为索引,或者切片。对于set和dict,key为hashable。key不存在引发KeyError异常__setitem __和__getitem__的访问类似,是设置值的方法__missing __字典或其子类使用__getitem__()调用时,key不存在执行该方法 #伪装成容器,必须具备容器的一些特征,如: iter(),len(),get(),set() class Cart: def __init__(self): self.items = [] #用list设定一个伪装容器 def additem(self,item): self.items.append(item) return self def __len__(self): #给容器增加一个判断长度的功能 return len(self.items) def __getitem__(self,index): #给容器增加一个用索引查找的功能 return self.items[index] def __setitem__(self,key,value): #给容器增加一个元素重新赋值的功能 return self.items[key] == value def __iter__(self): #将容器变为可迭代器 return iter(self.items) def __add__(self,other): #给容器增加一个增加元素的功能 self.items.append(other) return self def __str__(self): return str(self.items) p1 = Cart() p1.additem('cup') p1.additem('phone').additem('keyboard') print(p1) ----------------------------------------------------------- ['cup', 'phone', 'keyboard']

    可调用对象

    方法意义__call __类中定义一个该方法,实例就可以像函数一样调用

    举例:累加

    class Add: def __call__(self, *args): ret = 0 for i in args: ret += i self.ret = ret return self.ret adder = Add() print(adder(1,2,3)) ---------------------------------- 6
    最新回复(0)