python基础类的特殊成员(类的特殊内置属性和方法)
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python基础类的特殊成员(类的特殊内置属性和方法)相关的知识,希望对你有一定的参考价值。
- __foo__: 定义的是
特殊方法
,一般是系统定义名字 ,类似 __init__() 之类的。- _foo: 以单下划线开头的表示的是
protected 类型的变量
,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
- __foo: 双下划线的表示的是私有类型(private)的变量,
只能是允许这个类本身进行访问
。
Python 用下划线作为变量前缀和后缀
指定方法为特殊方法,下面介绍一些常用的特殊方法。(本文会根据自己遇到的内置属性和方法,随时更新!)
0. 特殊属性
先来看属性:
- Class.__doc__ # 类型帮助信息 ‘Class1 Doc.’
- Class.__name__ # 类型名称 ‘Class1’
- Class.__module__ # 类型所在模块 ‘main’
- Class.__bases__ # 类型所继承的基类 (<type ‘object’>,)
- Class.__dict__ # 类型字典,存储所有类型成员信息。 <dictproxy object at 0x00D3AD70>
- obj.__class__ # 类型 <class ‘__main__.Class1’>
- obj.__module__ # 实例类型所在模块 ‘__main__’
- obj.__dict__ # 对象字典,存储所有实例成员信息。 ‘i’: 1234
直接看程序会更清晰
class A:
'''A的帮助信息''' #给__doc__使用
def __init__(self, name, price):
self.name = name
self.price = price
def foo(self):
pass
def bar(self):
pass
a = A('口罩', 0.5)
#-----------------class---------------------
print(A.__doc__) #类的帮助信息
print(A.__name__) # 类的名字:A
print(A.__module__) ## __main__
print(A.__base__) ## A的基类:<class 'object'>
print(A.__dict__) #类别字典,类存储的成员信息
#---------------------obj-----------------------
print(a.__class__) #<class '__main__.A'>
print(a.__module__) # __main__
print(a.__dict__) #对象字典'name': '口罩', 'price': 0.5
1. 类的基础方法
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
初始化一个实例 | x = MyClass() | x.__init__() |
字符串的“官方”表现形式 | repr(x) | x.__irepr__() |
字符串的“非正式”值 | str(x) | x.__str__() |
字节数组的“非正式”值 | bytes(x) | x.__ibytes__() |
格式化字符串的值 | format(x, format_spec) | x.__iformat__(format_spec) |
1.1 __init__()
在创建实例对象时,调用该方法。
class A():
def __init__(self, name, age):
self.name = name
self.age = age
print('__init__被调用了!')
a = A('xiaoming', 22)
输出:
__init__被调用了!
1.2 __repr__()
该方法继承自object类。当创建我们用print打印对象时,会默认调用该方法得到我们关于类的信息。一般默认打印的信息为<xxxx object at 0x000000879>,我们可以对它的输出进行改变。如下:
class A():
def __repr__(self):
return '__repr__被调用了!'
a = A()
print(a)
输出:
__repr__被调用了!
1.3 __str__()
与repr类似。区别如下:
- __str__ 的返回结果可读性强。也就是说,__str__ 的意义是得到便于人们阅读的信息,就像上面的 ‘2019-10-20 20:59:47.003003’ 一样。
- __repr__ 的返回结果应更准确。__repr__ 存在的目的在于调试,便于开发者使用。将 __repr__ 返回的方式直接复制到命令行上,是可以直接执行的。
class A():
def __str__(self):
return '__str__被调用了!'
a = A()
print(a)
输出:
__str__被调用了!
2. 与迭代器类似(__iter__()与__next__())
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
遍历某个序列 | iter(seq) | seq.__iter__() |
从迭代器中获取下一个值 | next(seq) | seq.__next__() |
按逆序创建一个迭代器 | reversed(seq) | seq.__reversed__() |
iter与next常常一起使用,reversed方法并不常用,它是一个现有序列为参数,并将该序列中所有元素从尾到头以逆序排列生成一个新的迭代器。
class A():
def __init__(self,num):
self.num = num
self.start_num = -1
def __iter__(self):
print('__iter__被调用')
return self
def __next__(self):
print('__next__被调用')
self.start_num +=1
if(self.start_num >= self.num):
raise StopIteration()
return self.start_num
for i in A(5): #迭代5次
print(i)
输出:
__iter__被调用
__next__被调用
0
__next__被调用
1
__next__被调用
2
__next__被调用
3
__next__被调用
4
__next__被调用
3. 行为方式与函数类似(__call__())
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
遍历某个序列 | my_instance() | my_instance.__call__() |
把实例当做函数一样调用。
class A():
def __call__(self, *args, **kwargs):
print('__call__被调用')
print(args)
print(kwargs)
a = A()
a(1,2,q = 1)
输出:
__call__被调用
(1, 2)
'q': 1
4. 行为方式与序列类似的类
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
序列的长度 | len(seq) | seq.__len__() |
了解某序列是否包含特定的值 | x in seq | seq.__contains__(x) |
4.1 __len__()
可以计算实例长度。
class A():
def __len__(self):
print('__len__被调用')
return 10
a = A()
print(len(a))
输出:
__len__被调用
10
4.2 __contains__(x)
可以像序列一样遍历类
class A():
def __init__(self):
self.items = 'a':1, 'b':2,'c':3
def __contains__(self, item):
print('__contains__被调用')
return item in self.items
a = A()
print('a' in a)
print('d' in a)
输出:
__contains__被调用
True
__contains__被调用
False
5. 行为方式与字典类似
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
通过键来获取值 | x[key] | x.__getitem__(key) |
通过键来设置值 | x[key] = value | x.__setitem__(key, value) |
删除一个键值对 | del x[key] | x.__delitem__(key) |
为缺失键提供默认值 | x[nonexistent_key] | x.__missing__(nonexistent_key) |
5.1 __setitem__(key, value)
像字典一样设定键值对
class A():
def __setitem__(self, key, value):
print('__setitem__被调用')
a = A()
a[3] = 4
输出:
__setitem__被调用
5.2 __getitem__(key)
像字典一样取值
class A():
def __setitem__(self, key, value):
print('__setitem__被调用')
def __getitem__(self, item):
print('__getitem__被调用')
print("item: ",item)
return 10
a = A()
a['3'] = 4
print("-"*20)
print(a['3'])
输出:
__setitem__被调用
--------------------
__getitem__被调用
item: 3
10
5.3 __delitem__(key)
像字典一样删除键值对
class A():
def __setitem__(self, key, value):
print('__setitem__被调用')
def __delitem__(self, key):
print('__delitem__被调用')
a = A()
a['3'] = 4
del a[3]
输出:
__setitem__被调用
__delitem__被调用
6. 计算属性
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
获取一个计算属性(无条件的) | x.my_property | x.__getattribute__(‘my_property’) |
获取一个计算属性(后备) | x.my_property | x.__getattr__(‘my_property’) |
设置某属性 | x.my_property = value | x.__setattr__(‘my_property’,value) |
删除某属性 | del x.my_property | x.__delattr__(‘my_property’) |
列出所有属性和方法 | dir(x) | x.__dir__() |
6.1 __getattribute__(‘my_property’)
如果某个类定义了 __getattribute__() 方法,在 每次引用属性或方法名称时Python 都调用它(特殊方法名称除外,因为那样将会导致讨厌的无限循环)。
class A():
def __init__(self,num):
self.num = num
def __getattribute__(self, item):
print('__getattribute__被调用')
print(item)
return object.__getattribute__(self,item)
a = A(3)
print(a.num)
输出:
__getattribute__被调用
num
3
6.2 __dir__()
列出所有属性和方法
class A():
def __init__(self):
pass
a = A()
print(dir(a))
输出:
[‘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’]
7. 可比较的类
目的 | 所编写代码 | Python 实际调用 |
---|---|---|
相等 | x == y | x.__eq__(y) |
不相等 | x != y | x.__ne__(y) |
小于 | x < y | x.__lt__(y) |
小于或等于 | x <= y | x.__le__(y) |
大于 | x > y | x.__gt__(y) |
大于或等于 | x >= y | x.__ge__(y) |
布尔上上下文环境中的真值 | if x: | x.__bool__() |
如果定义了 __lt__() 方法但没有定义 __gt__() 方法,Python 将通过经交换的算子调用__lt__() 方法。然而,Python 并不会组合方法。例如,如果定义了__lt__() 方法和 __eq()__ 方法,并试图测试是否 x <= y,Python 不会按顺序调用__lt__() 和__eq()__ 。它将只调用__le__() 方法。
以上是关于python基础类的特殊成员(类的特殊内置属性和方法)的主要内容,如果未能解决你的问题,请参考以下文章