一个类中的魔法函数继承自 object 类
在Python的类中存在一些特殊的方法,这些方法都是 __方法__
格式,这种方法在内部均有特殊的含义,接下来我们来讲一些常见的特殊成员:
__init__
,初始化方法
class Foo(object): def __init__(self, name): self.name = name obj = Foo("小三")
__new__
,构造方法
class Foo(object): def __init__(self, name): print("第二步:初始化对象,在空对象中创建数据") self.name = name def __new__(cls, *args, **kwargs): print("第一步:先创建空对象并返回") return object.__new__(cls) # return super().__new__(cls) # 官方文档 obj = Foo("小三")
# 流程 # __new__(cls, *args, **kwargs) 用于创建一个空对象 # __init__(self) 初始化对象, 在空对象中创建数据 class A: def __init__(self, name, age): """ 接收 __new__() 的返回值,当作参数传递到 self 中。 当 obj = A() 类被对象示例化时, 触发 __init__() 函数。 """ # print(self) print(self) print("init") print(name) print(age) def __new__(cls, *args, **kwargs): """ 当类加() 执行时,触发 __new__() 方法 cls:表示当前的类 例如 A();本质是将 A 作为参数,传给 cls。 __new__ 函数的返回值是将 一个对象 作为 self 参数传入到 __init__(self) 函数中。 """ print(args) print(kwargs) print("new") print(cls.__name__) a = super().__new__(cls) print(a) return a # A("hello", age=10) # A.__new__(A, "hello", age=10)
__call__
class Foo(object): def __call__(self, *args, **kwargs): print("执行call方法") obj = Foo() obj()
__str__
class Foo(object): def __str__(self): return "哈哈哈哈" obj = Foo() data = str(obj) print(data)
__dict__
class Foo(object): def __init__(self, name, age): self.name = name self.age = age obj = Foo("小三",19) print(obj.__dict__)
__getitem__
、__setitem__
、__delitem__
class Foo(object): def __getitem__(self, item): pass def __setitem__(self, key, value): pass def __delitem__(self, key): pass obj = Foo("小三", 19) obj["x1"] obj['x2'] = 123 del obj['x3']
__enter__
、__exit__
class Foo(object): def __enter__(self): print("进入了") return 666 def __exit__(self, exc_type, exc_val, exc_tb): print("出去了") obj = Foo() with obj as data: print(data)
超前知识:数据连接,每次对远程的数据进行操作时候都必须经历。 1.连接 = 连接数据库 2.操作数据库 3.关闭连接
class SqlHelper(object): def __enter__(self): self.连接 = 连接数据库 return 连接 def __exit__(self, exc_type, exc_val, exc_tb): self.连接.关闭 with SqlHelper() as 连接: 连接.操作.. with SqlHelper() as 连接: 连接.操作...
# 面试题(补充代码,实现如下功能) class Context: def do_something(self): print('内部执行') with Context() as ctx: print('内部执行') ctx.do_something()
上下文管理的语法。
__add__
等。
class Foo(object): def __init__(self, name): self.name = name def __add__(self, other): return "{}-{}".format(self.name, other.name) v1 = Foo("alex") v2 = Foo("sb") # 对象+值,内部会去执行 对象.__add__方法,并将+后面的值当做参数传递过去。 v3 = v1 + v2 print(v3)
__iter__
迭代器
# 迭代器类型的定义: 1.当类中定义了 __iter__ 和 __next__ 两个方法。 2.__iter__ 方法需要返回对象本身,即:self 3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。 官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types # 创建 迭代器类型 : 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) 迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。 for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
生成器
# 创建生成器函数 def func(): yield 1 yield 2 # 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。 obj1 = func() v1 = next(obj1) print(v1) v2 = next(obj1) print(v2) 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
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 class Foo(object): def __iter__(self): return IT() obj = Foo() # 可迭代对象 for item in obj: # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法。 print(item)
# 基于可迭代对象&迭代器实现:自定义range class IterRange(object): def __init__(self, num): self.num = num self.counter = -1 def __iter__(self): return self def __next__(self): self.counter += 1 if self.counter == self.num: raise StopIteration() return self.counter class Xrange(object): def __init__(self, max_num): self.max_num = max_num def __iter__(self): return IterRange(self.max_num) obj = Xrange(100) for item in obj: print(item)
class Foo(object): def __iter__(self): yield 1 yield 2 obj = Foo() for item in obj: print(item)
# 基于可迭代对象&生成器 实现:自定义range class Xrange(object): def __init__(self, max_num): self.max_num = max_num def __iter__(self): counter = 0 while counter < self.max_num: yield counter counter += 1 obj = Xrange(100) for item in obj: print(item)
常见的数据类型:
v1 = list([11,22,33,44]) v1是一个可迭代对象,因为在列表中声明了一个 __iter__ 方法并且返回一个迭代器对象。
from collections.abc import 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__且返回迭代器对象。
class_name = "User" class_base = (object, ) class_body = """ def __init__(self, name, age): self.name = name self.age = age def func(self): print(self.name) """ class_dict = {} exec(class_body, globals(), class_dict) print(class_dict) class MyType(type): def __init__(self, class_name, class_bases=None, class_dict=None): super(MyType, self).__init__(class_name, class_bases, class_dict) def __call__(self, *args, **kwargs): obj = self.__new__(self, *args, **kwargs) self.__init__(obj, *args, **kwargs) return obj User = MyType(class_name, class_base, class_dict) user_obj = User("hxc", 18) print(user_obj.name)
class MyType(type): def __init__(self, class_name, class_bases=None, class_dict=None): super(MyType, self).__init__(class_name, class_bases, class_dict) # 此处继承调用的是父类 type 中的 __init__ 方法 def __call__(self, *args, **kwargs): # 当你申请对象时 就会触发此函数 object = ClassName() obj = self.__new__(self, *args, **kwargs) # 元类 type 中, 要求 __new__(self, *args, **kwargs) 是这种方式传参 self.__init__(obj, *args, **kwargs) class Foo(object): __metaclass__ = MyType # Foo = MyType() def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls) # 父类创建的空对象 本身是一种数据结构,可以 对象.变量 = "value" 形式赋值 obj = Foo("hxc") # obj = Foo("hxc") = MyType()("hxc") 此时触发 MyType 中的 __call__ 方法 print(obj.name) # 代码执行顺序: # 1 Foo("hxc") # 2 __metaclass__ = MyType 相当于执行 Foo = MyType() # 3 执行 MyType 中的 __init__ 函数 class_name:类名; class_bases:父类; class_dict: 名称空间 # 4 执行 MyType 中的 __call__ 函数 得到返回值 返回给对象 obj