我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈
__dict__ # 类的属性和值
__bases__ # 类的所有父类构成元组
__doc__ # 类的文档字符串
__name__ # 类名
__module__ # 类定义所在的模块
class B(object):
pass
class Person(B,A):
"""Person类描述"""
age = 18
def test(self):
"""test方法描述"""
print('test方法')
print(Person.__dict__) # 输出:{'__module__': '__main__', '__doc__': 'Person类描述', 'age': 18, 'test': }
print(Person.__bases__) # 输出:(, )
print(Person.__doc__) # 输出:Person类描述
print(Person.__name__) # 输出:Person
print(Person.__module__) # 输出:__main__(主模块)
__dict__ # 实例的属性
__class__ # 实例对应的模块.类
class A(object):
pass
class B(object):
pass
class Person(B,A):
"""Person类描述"""
age = 18
def __init__(self):
a = 99
self.b = 199
def test(self):
"""test方法描述"""
c = 100
self.d = 200
print('test方法')
p = Person()
p.name = '失心疯'
print(p.__dict__) # 输出:{'b': 199, 'name': '失心疯'}
print(p.__class__) # 输出:(主模块.Person类)
__init__
方法class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.source = '地球'
p1 = Person('张三', 18)
p2 = Person('李四', 36)
print(p1.name, p1.age, p1.source) # 输出:张三 18 地球
print(p2.name, p2.age, p2.source) # 输出:李四 36 地球
__str__
方法__repr__
方法__str__方法
示例class Person(object):
def __init__(self):
print('实例化对象的时候,自动调用__init__方法')
self.name = '失心疯'
self.age = 36
def __str__(self):
return f'调用__str__方法,我的名称是:{self.name}, 年龄是:{self.age}'
p = Person() # 输出:实例化对象的时候,自动调用__init__方法
print(p) # 输出:调用__str__方法,我的名称是:失心疯, 年龄是:36
__repr__方法
示例class Person(object):
def __init__(self):
print('实例化对象的时候,自动调用__init__方法')
self.name = '失心疯'
self.age = 36
def __str__(self):
return f'调用__str__方法,我的名称是:{self.name}, 年龄是:{self.age}'
def __repr__(self):
return f'调用__repr__方法,我的名称是:{self.name},年龄是:{self.age}'
p = Person() # 输出:实例化对象的时候,自动调用__init__方法
print(p) # 输出:调用__str__方法,我的名称是:失心疯, 年龄是:36
s = str(p)
print(s, type(s)) # 调用__str__方法,我的名称是:失心疯, 年龄是:36
r = repr(p)
print(r, type(r)) # 调用__repr__方法,我的名称是:失心疯,年龄是:36
p # 无输出
__str__
和__repr__
的区别
__str__
和__repr__
大致差不多,都是通过一个字符串来描述这个对象
但是__str__
和__repr__
面向的角色不一样
__str__
面向的角色是用户,看起来比较友好,易懂__repr__
面向的角色是开发人员(Python解释器),是为了让开发人员看到这个实例的本质(如:类型、内存地址),或者Python解释器通过eval这个函数再次把它处理成相关的实例对象在PyCharm中执行情况
在Python解释器中执行情况
eval函数转换
import datetime
t = datetime.datetime.now()
print(t) # 执行__str__方法,输出:2023-11-04 21:07:49.773549
print(repr(t)) # 行__repr__方法,输出:datetime.datetime(2023, 11, 4, 21, 7, 49, 773549)
res = repr(t)
print(res) # 输出:datetime.datetime(2023, 11, 4, 21, 22, 53, 180571)
print(eval(res)) # eval函数,输出:2023-11-04 21:09:06.275814
# eval函数:将字符串str当成有效的表达式来求值并返回计算结果
# eval(repr(t)) 相当于是下面的步骤
aa = datetime.datetime(2023, 11, 4, 21, 7, 49, 773549)
print(aa)
作用
实现方法
__call__方法
默认实例化对象是不能被调用的
class Person(object):
pass
p = Person()
p()
添加__call__
方法后,实例化对象就可以实现调用功能
class Person(object):
def __call__(self, *args, **kwargs):
print('__call__方法,实现调用功能')
p = Person()
p()
同样,实例对象在调用的时候也是可以传入参数的
class Person(object):
def __call__(self, *args, **kwargs):
print('__call__方法,实现调用功能')
print('接收参数:', args, kwargs)
p = Person()
p(123, 456, 888, name='失心疯')
应用场景
# 正常情况
# def penFatory(pen_type, pen_color):
# print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
#
#
# gb1 = penFatory('钢笔','红色')
# gb2 = penFatory('钢笔','蓝色')
# gb3 = penFatory('钢笔','黄色')
# gb4 = penFatory('钢笔','绿色')
# 在生成多种颜色的钢笔时,每次都要重复输入笔的类型:钢笔,这个比较累赘
# 通过偏函数方式来优化
# # 方式一:自定义偏函数
# def penFatory(pen_type, pen_color):
# print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
#
# # 定义偏函数
# def newPenFatory(new_color, new_type='钢笔'):
# penFatory(new_type, new_color)
#
#
# gb1 = newPenFatory('红色')
# gb2 = newPenFatory('蓝色')
# gb3 = newPenFatory('黄色')
# gb4 = newPenFatory('绿色')
# 方式二:使用标准库functools
import functools
# 这里需要注意的是,需要将定义偏函数时传递的参数放到最后,否在则定义实例的时候会报错
def penFatory(pen_color, pen_type):
print(f'生产一支{pen_type}类型的笔,颜色是:{pen_color}')
newPenFatory = functools.partial(penFatory, pen_type='钢笔')
gb1 = newPenFatory('红色')
gb2 = newPenFatory('黄色')
gb3 = newPenFatory('蓝色')
gb3 = newPenFatory('绿色')
__call__
方法# 使用__call__方法
class PenFatory(object):
def __init__(self, pen_type):
self.type = pen_type
def __call__(self, pen_color):
print(f'生产一支{self.type}类型的笔,颜色是:{pen_color}')
gb = PenFatory('钢笔') # 实例化对象的时候,定义其类型为:钢笔
gb('黄色') # 每次调用,设置其颜色
gb('绿色')
gb('蓝色')
gb('红色')
__setitem__
方法__getitem__
方法__delitem__
方法class Person(object):
def __setitem__(self, key, value):
print('setitem', key, value)
def __getitem__(self, item):
print('getitem', item)
def __delitem__(self, key):
print('delitem', key)
p[1] = 666
p['s'] = '失心疯'
p[1]
p['s']
del p['s']
del p[1]
class Person(object):
def __init__(self):
self.cache = {}
def __setitem__(self, key, value):
self.cache[key] = value
def __getitem__(self, item):
return self.cache[item]
def __delitem__(self, key):
del self.cache[key]
p = Person()
p['name'] = '失心疯'
print(p['name'])
del p['name']
__setspic__
、__getspic__
、__delspic__
三个方法实现__setitem__
、__getitem__
、__delitem__
class Person(object):
def __init__(self):
self.list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def __setitem__(self, key, value):
print(key, value)
self.list[key] = value
def __getitem__(self, item):
print(item)
return self.list[item]
def __delitem__(self, key):
print(key)
del self.list[key]
p = Person()
# 通过切片操作进行值的修改(切片操作不能直接添加值)
p[0:4:2] = ['a', 'b'] # 执行__setitem__方法,输出:slice(0, 4, 2) ['a', 'b']
# 从输出结果可以看到,key是一个slice实例对象(切片对象)
# 查看 slice 切片实例对象 源码
# start = property(lambda self: 0) # 获取起始索引
# """:type: int"""
#
# step = property(lambda self: 0) # 获取步长
# """:type: int"""
#
# stop = property(lambda self: 0) # 获取结束索引
# """:type: int"""
# 通过切片获取值
p[0:4:1] # 执行__getitem__方法,输出:slice(0, 4, 1)
# 通过切片删除值
del p[0:2:1] # 执行__delitem__方法,输出:slice(0, 2, 1)
p[:] # 通过删除操作后,输出:['b', 4, 5, 6, 7, 8, 9]
__setitem__
、__getitem__
、__delitem__
三个方法统一管理,所以我们在编写这三个方法的时候需要进行容错处理class Person(object):
def __init__(self):
self.cache = {}
self.list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def __setitem__(self, key, value):
# 判断key是否是slice类的子类
if issubclass(key, slice):
self.list[key] = value
else:
self.cache[key] = value
def __getitem__(self, item):
if issubclass(item, slice):
return self.list[item]
else:
return self.cache[item]
def __delitem__(self, key):
if issubclass(key, slice):
del self.list[key]
else:
del self.cache[key]
__eq__:是否等于(==)比较时,自动执行(没有写__ne__方法时,不等于比较时,会执行该方法)
__ne__:是否不等于(!=)比较时,自动执行(不等于比较时,优先执行该方法)
__gt__:是否大于(>)比较时,自动执行
__ge__:是否大于等于(>=)比较时,自动执行
__lt__:是否小于(<)比较时,自动执行
__le__:是否小于等于(<=)比较时,自动执行
class Person(object):
def __init__(self, age, width):
self.age = age
self.width = width
# 通过下面方法设定两个对象进行比较时,比较的是age属性值
def __eq__(self, other):
"""实例对象进行 == 比较时,自动调用"""
return '__eq__方法', self.age == other.age
def __ne__(self, other):
"""实例对象进行 != 比较时,自动调用"""
return '__ne__方法', self.age != other.age
def __gt__(self, other):
"""实例对象进行 > 比较时,自动调用"""
return '__gt__方法', self.age > other.age
def __ge__(self, other):
"""实例对象进行 >= 比较时,自动调用"""
return '__ge__方法', self.age >= other.age
def __lt__(self, other):
"""实例对象进行 < 比价时,自动调用"""
return '__lt__方法', self.age < other.age
def __le__(self, other):
"""实例对象进行 <= 比较时,自动调用"""
return '__le__方法', self.age <= other.age
p1 = Person(18, 160)
p2 = Person(17, 180)
print(p1 == p2) # 输出:('__eq__方法', False)
print(p1 != p2) # 输出:('__ne__方法', True)
print(p1 > p2) # 输出:('__gt__方法', True)
print(p1 >= p2) # 输出:('__ge__方法', True)
print(p1 < p2) # 输出:('__lt__方法', False)
print(p1 <= p2) # 输出:('__le__方法', False)
class Person(object):
def __init__(self, age, name):
self.age = age
self.name = name
def __lt__(self, other):
"""实例对象进行 < 比价时,自动调用"""
print('self:', self.name, self.age)
print('other:', other.name, other.age)
return self.age < other.age
p1 = Person(18, 'p1')
p2 = Person(19, 'p2')
print(p1 < p2)
# self: p1 18
# other: p2 19
# True
print(p1 > p2) # 实际执行的是 p2 < p1 比较
# self: p2 19
# other: p1 18
# False
class Person(object):
def __init__(self, age):
self.age = age
def __eq__(self, other):
"""实例对象进行 == 比较时,自动调用"""
return self.age == other.age
def __lt__(self, other):
"""实例对象进行 < 比价时,自动调用"""
return self.age < other.age
p1 = Person(18)
p2 = Person(19)
print(p1 == p2) # 输出:False
print(p1 < p2) # 输出:True
print(p1 <= p2) # 报错:TypeError: '<=' not supported between instances of 'Person' and 'Person'
functools.total_ordering
)实现方法叠加操作(实现==和<方法,即可实现 != 、> 、>=、<=的比较)import functools
@functools.total_ordering
class Person(object):
def __init__(self, age, name):
self.age = age
self.name = name
def __eq__(self, other):
"""实例对象进行 == 比较时,自动调用"""
print('__eq__方法')
return self.age == other.age
def __lt__(self, other):
"""实例对象进行 < 比价时,自动调用"""
print('__lt__方法', self.name, other.name)
return self.age < other.age
# print(Person.__dict__)
"""
输出:{'__module__': '__main__', '__init__': ,
'__eq__': , '__lt__': ,
'__dict__': , '__weakref__': ,
'__doc__': None, '__hash__': None,
'__gt__': ,
'__le__': ,
'__ge__': }
"""
p1 = Person(29, 'p1')
p2 = Person(29, 'p2')
print(p1 == p2) # 输出:__eq__方法 True
print(p1 != p2) # 输出:__eq__方法 False
#
print(p1 < p2) # 输出:__lt__方法 False
print(p1 <= p2) # 输出:__lt__方法 __eq__方法 True
# 首先执行 < 判断,返回True, 则结束,
# 返回False,再执行 == 判断
#
print(p1 > p2) # 输出:__lt__方法 __eq__方法 False
# 首先执行 < 判断,返回True, 则结束,返回:<判断结果取反False
# 返回False, 再执行 == 判断,返回:==判断结果取反
print(p1 >= p2) # 输出:__lt__方法 True
# 首先执行 < 判断,最终返回:<判断结果取反
# < 判断结果为True,则不会是大于和等于,所以返回False
# < 判断结果为False, 则不是大于就是等于,所以返回True
__bool__
方法控制# 对比示例
class Person(object):
pass
p = Person()
# 非空即真,p是实例对象,并非为空,所以判断为真,执行下面代码
if p:
print('xxxxx')
else:
print('yyyyy')
# 输出:xxxxx
# __bool__方法演示示例
class Person(object):
def __bool__(self):
return False
p = Person()
if p:
print('xxxxxx')
else:
print('yyyyyy')
# 输出:yyyyyy
__bool__
方法,我们就可以控制实例对象判断的返结果class Person(object):
def __init__(self, age, name):
self.age = age
self.name = name
def __bool__(self):
return self.age > 18
p1 = Person(16, 'p1')
p2 = Person(26, 'p2')
ps = [p1, p2]
for p in ps:
if p:
print(f'{p.name}已经成年啦')
else:
print(f'{p.name}还是未成年')
# 输出结果
# p1还是未成年
# p2已经成年啦
作用
for...in..
遍历 和 next()
函数访问操作)实现步骤
__getitem__
方法__iter__
+ __next__
方法(优先级更高)示例代码
对比示例
class Person(object):
pass
p = Person()
for i in p:
print('xxxx')
# 输出结果:报错
# TypeError: 'Person' object is not iterable
__getitem__
方法示例
class Person(object):
def __init__(self):
self.age = 18
def __getitem__(self, item):
self.age += 1
if self.age > 30:
raise StopIteration('年龄太大了...')
return self.age
p = Person()
# for..in..操作会不断调用__getitem__方法,直到该方法抛出异常(raise StopIteration)
for i in p:
print(i)
这里的for..in..
遍历是直接调用__getitem__
方法
__iter__
+ __next__
方法示例
class Person(object):
def __init__(self):
self.age = 18
def __iter__(self):
print('xxxx')
"""实例对象调用iter()方法的时候自动调用,需要返回一个迭代器(iterator)对象"""
return self
def __next__(self):
"""实例对象使用next()函数的时候自动调用该方法"""
self.age += 1
if self.age > 30:
raise StopIteration('年龄太大了!')
return self.age
p = Person()
# 通过for..in..遍历
# 1、先通过iter()方法将实例对象转换成一个迭代器
# iter(p) # 输出:xxxx
# 2、再调用next()方法取值
for i in p:
print(i)
# 通过next()函数取值
print(next(p))
print(next(p))
print(next(p))
print(next(p))
这里的for..in..
实际是先通过iter()
方法将实例对象转换成迭代器对象,再调用next()
方法
iter()
方法的时候会自动调用__iter__()
方法next()
方法的时候会自动调用__next__()
方法可使用next()
方法:对象内部实现__next__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __next__(self):
self.age += 1
if self.age > 20:
raise StopIteration
return self.age
p = Person()
print(next(p)) # 19
print(next(p)) # 20
import collections
# 判断实例对象是否是可迭代对象
print(isinstance(p, collections.Iterable)) # False
# 判断实例对象是否是迭代器
print(isinstance(p, collections.Iterator)) # False
可迭代对象:对象内部实现__iter__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __iter__(self):
return self
p = Person()
# print(next(p)) # 报错:TypeError: 'Person' object is not an iterator
# print(next(p)) # 报错:TypeError: 'Person' object is not an iterator
from collections import abc
# 判断实例对象是否是可迭代对象
print(isinstance(p, abc.Iterable)) # True
# 判断实例对象是否是迭代器
print(isinstance(p, abc.Iterator)) # False
迭代器:对象内部既要实现__next__()
方法又要实现__iter__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __iter__(self):
return self
def __next__(self):
self.age += 1
if self.age > 20:
raise StopIteration
return self.age
p = Person()
from collections import abc
# 判断实例对象是否是可迭代对象
print(isinstance(p, abc.Iterable)) # True
# 判断实例对象是否是迭代器
print(isinstance(p, abc.Iterator)) # False
print(next(p)) # 19
print(next(p)) # 20
iter()
函数的使用
语法
iter(实例对象)
iter(可执行对象, 值)
iter(实例对象)
模式将实例对象转换成迭代器
想要通过for..in..
遍历自定义实例对象,可以通过以下两种方式
__getitem__()
方法__iter__()
方法和__next__()
方法要想使用iter()
方法将自定义实例转换成一个迭代器,必须通过以下两种方法中的任意一种
__getitem__()
方法__iter__()
方法和__next__()
方法示例1:实例对象内部实现__getitem__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __getitem__(self, item):
self.age += 1
if self.age > 25:
raise StopIteration
return self.age
p = Person()
pt = iter(p)
print(pt) #
for i in pt:
print(i)
# 输出结果
# 19
# 20
# 21
# 22
# 23
# 24
# 25
示例2:在实例对象内部只实现__iter__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __iter__(self):
return self
p = Person()
pt = iter(p) # 报错:TypeError: iter() returned non-iterator of type 'Person'
# 报错原因:
# 使用iter()函数时会自动调用__iter__()方法,__iter__()方法要求返回值是一个迭代器,此处返回的是self(示例对象本身)
# 但是此时的Person类内部仅仅只实现了__iter__()方法,并没有实现__next__()方法,所以Person类实例化出来的对象仅仅是一个可迭代对象并不是一个迭代器
示例3:在示例对象内部实现__iter__()
方法和__next__()
方法
class Person(object):
def __init__(self):
self.age = 18
def __iter__(self):
return self
def __next__(self):
self.age += 1
if self.age > 25:
raise StopIteration
return self.age
p = Person()
pt = iter(p)
print(pt) # 输出:<__main__.Person object at 0x000001B574C4DFD0>
# 执行iter()函数,实际就是执行的自定义类对象中的__iter__()方法,返回的是self(Person实例化对象本身p)
# 因为Person类内部实现了`__iter__()`方法和`__next__()`方法,所以实例化出来的对象p就是一个迭代器
# 因此:pt就是p,就是一个迭代器,就可以通过for..in..遍历,也可以通过next()函数访问值
print(pt == p, pt is p) # 输出:True True
# for i in pt:
# print(i)
print(next(p))
print(next(p))
__init__(self)
# 创建实例化对象的时候会自动调用
__setattr__(self, key, value)
# 实例新增/修改属性的时候自动调用
__str__(self)
# 访问实例对象的时候自动调用
__repr__(self)
# 访问实例对象的时候自动调用
__setitem__(self, key, value)
# 实例对象以key-value的方式添加属性和值的时候自动调用
# 实例对象通过切片进行值修改的时候自动调用,key是slice类型
__getitem__(self, item)
# 实例对象以key-value的方式获取属性值的时候自动调用
# 实例对象通过切片进行值获取的时候自动调用,item是slice类型
# 实例对象进行for..in..遍历时候不断调用该方法,直到方法抛异常,优先级低于__iter__方法
__delitem__(self, key)
# 实例对象以key-value的方式删除属性和值的时候自动调用
# 实例对象通过切片进行值删除的时候自动调用,key是slice类型
__eq__(self, other):
# 实例对象进行 == 比较时,自动调用
__ne__(self, other):
# 实例对象进行 != 比较时,自动调用
__gt__(self, other):
# 实例对象进行 > 比较时,自动调用
__ge__(self, other):
# 实例对象进行 >= 比较时,自动调用
__lt__(self, other):
# 实例对象进行 < 比价时,自动调用
__le__(self, other):
# 实例对象进行 <= 比较时,自动调用