元类
今日内容概要
- 面向对象的魔法方法
- 魔法方法笔试题
- 元类简介
- 创建类的两种方式
- 元类定制类的产生行为
- 元类定制对象的产生行为
- 魔法方法下之双下new
- 设计模式简介
面向对象的魔法方法
魔法方法:类中定义的双下方法都称之为魔法方法
不需要人为调用 在特定的条件下回自动调用
-
_init_
""" 1.__init__ 当类名加括号的时候 会自动调用 __init__ 方法 """ class A: def __init__(self, name): print("我是__init__哦") self.name = name A("jason")
-
_str_
""" 1.__str__ 当对象被打印的时候会自动执行,产生该对象的类里面的__new__方法 打印出__new__ 的返回值。 返回值只能是字符串类型 """ class A: def __init__(self): pass def __str__(self): return "哈哈" obj = A() print(obj)

-
_call_
""" 3.__call__ 就是能不能加括号, 如果对象加括号就是在调用类里面的__call__方法 类加括号就是在调用元类里面的__call__ 方法 """ class A: pass obj = A() obj()
class A: def __call__(self, *args, **kwargs): pass obj = A() obj()
-
_getattr_
""" 4.__getattr__ 当对象点不存在的名字的时候回自动调用__getattr__ 如果点的名字存在则不会调用__getattr__ """ class A: def __init__(self, name): self.name = name def __getattr__(self, item): print(item) print("我是__getattr__") return 123 obj = A("jason") print(obj.name)
class A: def __init__(self, name): self.name = name def __getattr__(self, item): print(item) print("我是__getattr__") return 123 obj = A("jason") print(obj.age)
-
_getattribute_
""" 5.__getattribute__ 不管对象点的名字存在不存在 则都会执行__getattribute__方法 """ class A: def __init__(self, name): self.name = name def __getattribute__(self, item): print(item) return 123 obj = A("jason") print(obj.name) print(obj.age)
-
_setattr_
""" 6.__setattr__ 只要 是 对象.名字 = 数据值 给对象添加或者修改数据的时候自动调用 对象.名字 = 数据值 """ class A: def __init__(self, name): self.name = name def __setattr__(self, key, value): print("我是 __setattr__") obj = A("jason") obj.name = "set"
-
_enter_,_exit_
""" 7.__enter__ , __exit__ __enter__当对象被当作with上下文管理操作的对象开始自动触发 并且该方法返回什么 as 后面的变量名就会接收到什么 __exit__当对象被当作with上下文管理操作的对象结束自动触发 """ class A: def __enter__(self): return 123 def __exit__(self, exc_type, exc_val, exc_tb): print(456) obj = A() with obj as f: print(f)
魔法方法笔试题
"""
1.补全下列代码使得运行不报错即可
分析: Context 加括号产生对象 with 了一个对象
所以类里面有个
因为__enter__ 返回什么 f接收什么
"""
class Context:
def do_sonmething(self):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
with Context() as f:
f.do_sonmething()
"""
2.自定义字典类型并让字典能够通过句点符的方式操作键值对
分析: 自定义字典 那么先继承字典
能够点名字 __getattr__
也能点名字 修改 对象.名字 = 数据值 __setattr__
"""
class Mydict(dict):
def __getattr__(self, item):
return self.get(item)
def __setattr__(self, key, value):
# 因为 实例化的对象是字典 所以 我们直接按字典来就行
self[key] = value
d1 = Mydict()
d1.name = "jason"
print(d1.name)
print(d1)

""" 如果你不写__setattr__方法
他会添加到对象的名称空间里面 而不是对象里面
"""
class Mydict(dict):
def __getattr__(self, item):
return self.get(item)
d1 = Mydict()
d1.name = "jason"
print(d1.name)
print(d1)
print(d1.__dict__)

元类简介
元类 就是产生类的类叫元类
"""
type 其实查看的是产生对象的类名
"""
class A:
pass
obj = A()
print(type(obj)) # <class '__main__.A'>
"""
type对象 是产生该对象的类名 那type 类呢
"""
print(type(A)) # <class 'type'>
"""
type 类 我们得到了type
那么产生类的类是type
结论:我们定义的类其实都是由type类产生的>>>:元类(产生类的类)
"""
创建类的两种方式
"""
方式一:
class 关键字
"""
class A:
pass
"""
方式二
利用元类type 创建
type 源码
type(object) -> the object's type
type(name, bases, dict) -> a new type
第一条是 type一个对象回返回 对象的类型
第二条 type里面传一个类名 类的父类元组形式 名称空间
会得到一个新类
"""
class_name = "Student"
class_base = ()
class_dict = {}
class_info = """
school_name = '哈哈学院'
def __init__(self, name):
self.name = name
"""
exec(class_info, {}, class_dict)
Student = type(class_name, class_base, class_dict)
print(type(Student))
obj = Student("jason")
print(obj.name)
print(obj.school_name)

元类定制类的产生行为
"""
类是由元类加括号产生的 元类加括号会执行__init__ 方法
要求 必须类名开头字母大写才可以 不然报错
"""
# 只有继承了type 才叫元类
class Mytype(type):
def __init__(self, *args, **kwargs):
print(args, kwargs)
if not args[0].istitle():
raise TypeError("类名开头必须大写")
super().__init__(*args, **kwargs)
class student(metaclass=Mytype):
pass

元类定制对象的产生行为
"""
对象加括号 会执行产生对象类的__call__方法
类加括号 会执行产生类的类的__call__方法
要求 给对象加独有数据的时候 必须采用关键字传参
类加括号产生对象 类加括号 调用元类的__call__
在__call__ 里操作
"""
class Mytype(type):
def __call__(self, *args, **kwargs):
print(args, kwargs)
if args:
raise TypeError("只能关键字传参")
return super().__call__(*args, **kwargs)
class Student(metaclass=Mytype):
def __init__(self, name, age):
self.name = name
self.age = age
Student("jaosn", "age")

魔法方法之双下new
class Mytype(type):
def __call__(self, *args, **kwargs):
"""
元类里面的__call__ 会做三件事
1. 调用self 的__new__ 方法产生一个空对象
2. 把空对象 当成第一个参数传给 self 下的 __init__方法
3. 把这个被__init__ 方法操作过的 空对象(现在已经不是空对象了)
返回出去
"""
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
return obj
class Student(metaclass=Mytype):
def __init__(self, name, age):
self.name = name
self.age = age
obj = Student("jaosn", "age")
print(obj.name)
设计单例模式
-
设计模式
前人通过大量的验证创建出来解决一些问题的固定方法
-
IT行业
23种
创建型
结构型
行为型
-
单例模式
类加括号无论多少次永远只会产生一个对象
目的:
当类中后很多非常强大的方法 我们在过程中很多地方都需要使用
如果不做单例 会产生很多无用的对象浪费存储空间
我们想使用单例模式 整个程序就用一个对象

浙公网安备 33010602011771号