python中的特殊成员
__new__()
class Foo(object):
def __init__(self, name):
self.name = name
obj = Foo("man!")
class Foo(object):
def __init__(self, name):
print("第二步:初始化对象,在空对象中创建数据")
self.name = name
def __new__(cls, *args, **kwargs):
print("第一步:先创建空对象并返回")
return object.__new__(cls)
obj = Foo("man!")
上面两段代码都可以正常执行,__new__ 是在Object类里自动实现的\
在第二段代码中,return object.__new__(cls) 返回给__init__
总的过程:
第一步先创建空对象并返回
第二步:初始化对象,在空对象中创建数据
call()
class Foo(object):
def __call__(self, *args, **kwargs):
print("执行call方法")
obj = Foo()
obj()
输出结果:
执行call方法
这个方法是python中是在对象后加括号,也可以理解为调用对象,最后是调用对象中call()
__str__
class Foo(object):
def __str__(self):
return "哈哈哈哈"
obj = Foo()
print(obj)
输出结果:
哈哈哈哈
一般我们直接打印对象会输出对象的地址,但是对象方法中使用了__str__,那么打印对象输出___str___方法的返回值
__dic__
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo("man",42)
print(obj.__dict__)
输出结果:
{"name":"man","age":42}
调用___dic___函数,将当前对象属性以键值对形式输出
__getitem__、__setitem__、__delitem__
对象属性的操作与操作字典类似
class Foo(object):
def __getitem__(self, item):
print(item)
def __setitem__(self, key, value):
self.key = value
def __delitem__(self, key):
pass
obj = Foo("man", 42)
obj["x1"]
obj['x2'] = 123
del obj['x3']
输出结果:
x1
添加了上面的几种方法,对象可以做类似字典的操作,方法内部实现什么可以自己写
__enter__、__exit__
上下文管理语法
1.with语法用于简化对象操作,自动执行enter和exit方法。
2.enter和exit方法用于上下文管理,确保对象操作前后正确关闭。
3.通过with语法可以简化代码,提高代码可读性和可维护性。
class Foo(object):
def __enter__(self):
print("进入了")
return abc
def __exit__(self, exc_type, exc_val, exc_tb):
print("出去了")
obj = Foo()
# __enter__ return 返回的值给了data
with obj as data:
print(123)
print(data)
输出结果:
进入了
123
abc
出去了
上下文管理, 操作对象前后可以做一些操作\
比如操作数据库前, ___enter___函数来连接数据库, ___exit___函数来关闭数据库
# 伪代码
class SqlHelper(object):
def __enter__(self):
self.连接 = 连接数据库
return 连接
def __exit__(self, exc_type, exc_val, exc_tb):
self.连接.关闭
with SqlHelper() as 连接:
连接.操作..
with SqlHelper() as 连接:
连接.操作...
__add__ 等
允许对象间进行相加操作(为什么是__add__ 等,因为除了相加之外还有加减乘除等等的操作)
class Foo(object):
def __init__(self, name):
self.name = name
def __add__(self, other):
return "{}-{}".format(self.name, other.name)
v1 = Foo("man")
v2 = Foo("out")
# 对象+值,内部会去执行 对象.__add__方法,并将+后面的值当做参数传递过去。
v3 = v1 + v2
print(v3)
输出结果:mam - out
从上面的代码可以看出,当对象之间进行加法操作就会触发__add__方法
__iter__
迭代器
迭代器类型的定义:
1.当类中定义了 __iter__ 和 __next__ 两个方法。
2.__iter__ 方法需要返回对象本身,即:self
3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
官方文档:docs.python.org/3/library/s…
# 创建 迭代器类型 :
class IT(object):
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 根据类实例化创建一个迭代器对象:
obj1 = IT()
# v1 = obj1.__next__()
# v2 = obj1.__next__()
# v3 = obj1.__next__() # 抛出异常
v1 = next(obj1) # obj1.__next__()
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = IT()
for item in obj2:
# 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象)
print(item)
for循环遍历一个迭代器对象时,会有三个步骤:
- for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,
- 迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
- 然后不断执行的next取值(有异常StopIteration则终止循环)。
生成器
创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。 如果按照迭代器的定义来看,其实生成器类也是一种特殊的迭代器类(生成器也是一种特殊的迭代器)。
# 创建生成器函数
def func():
yield 1
yield 2
obj1 = func()
v1 = next(obj1)
print(v1)
v2 = next(obj1)
print(v2)
# 到此抛出StopIteration
v3 = next(obj1)
print(v3)
obj2 = func()
for item in obj2:
print(item)
可迭代对象
如果一个类中有__iter__方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。
class Foo(object):
def __iter__(self):
return 迭代器对象(生成器对象)
obj = Foo() # obj是 可迭代对象。
# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
pass
给大家举一个例子
v1 = range(10)
# 发现v1的方法中只有__iter__,没有__next__,所以v1是可迭代对象
print("v1:", v1.__dir__())
# 可迭代对象通过__iter__()获得迭代器
v2 = v1.__iter__()逐步取值
# 迭代器执行__next__()
print(v2.__next__())
print(v2.__next__())
print(v2.__next__())
print(v2.__next__())
输出:
v1: ['__new__', '__repr__', '__hash__', '__getattribute__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__iter__', '__bool__', '__len__', '__getitem__', '__contains__', '__reversed__', '__reduce__', 'count', 'index', 'start', 'stop', 'step', '__doc__', '__str__', '__setattr__', '__delattr__', '__init__', '__reduce_ex__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
0
1
2
3
常见的数据结构:
l1 = list([1, 2, 3, 4, 5, 6])
print(dir(l1))
l2 = l1.__iter__()
print(l2.__next__())
print(l2.__next__())
print(l2.__next__())
输出:
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
1
2
3
l1是一个可迭代对象,因为在列表中声明了一个 __iter__ 方法并且返回一个迭代器对象。\
from collections.abc import Iterator, Iterable # Iterator(迭代器), Iterable(迭代对象)
v1 = [11, 22, 33]
print( isinstance(v1, Iterator) ) # false,判断是否是迭代器;判断依据是__iter__ 和 __next__。
v2 = v1.__iter__()
print( isinstance(v2, Iterator) ) # True
v1 = [11, 22, 33]
print( isinstance(v1, Iterable) ) # True,判断依据是是否有 __iter__且返回迭代器对象。
v2 = v1.__iter__()
print( isinstance(v2, Iterable) ) # True,判断依据是是否有 __iter__且返回迭代器对象。
\
\