特殊属性
属性 | 说明 |
---|---|
__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 __
- hash
- bool
- 可视化
- 运算符重载
- 容器和大小
- 可调用对象
- 上下文管理
- 反射
- 描述器
- 其他杂项
实例化
方法 | 意义 |
---|---|
__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