python 面向对象专题:元类type反射函数与类的区别特殊的双下方法
Posted 秋华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 面向对象专题:元类type反射函数与类的区别特殊的双下方法相关的知识,希望对你有一定的参考价值。
1. 元类type
-
type:获取对象从属的类
Python中一切皆对象,类在某种意义上也是一个对象
Python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的
# type 获取对象从属于的类 print(type(A)) print(type(str)) print(type(dict))
-
type与object的关系:
object类是type类的一个实例 print(type(object))
object类是type类的父类 print(issubclass(type,object))
2. 反射
-
定义:通过字符串操作对象的方式,程序对自己内部代码的一种自省方式
-
内置函数:hasattr getattr setattr delattr (attr 是属性的意思)
-
反射可以作用的对象:实例对象,类,本模块,其他模块
从对象角度应用反射
class A: country = \'中国\' def __init__(self,name,age): self.name = name self.age = age def func(self): print(\'in A func\') obj = A(\'张三\',66) # hasattr: 判断有无属性 print(hasattr(obj,\'name\')) print(hasattr(obj,\'country\')) # 报错 print(hasattr(obj,\'func\')) # 报错 # getattr: 获取属性 if hasattr(obj,\'name\'): getattr(obj,\'name\') # setattr: 设置属性/delattr: 删除属性 setattr(obj,\'sex\',\'男\') delattr(obj,\'name\')
从类的角度应用反射
class A: country = \'中国\' def __init__(self,name,age): self.name = name self.age = age def func(self): print(self) print(\'in A func\') if hasattr(A,\'func\'): obj = A(\'张三\', 26) getattr(obj,\'func\')() getattr(A,\'func\')(obj)
从其他模块应用反射
import tbjx # 1. 找到tbjx对象的C类,实例化一个对象. obj = getattr(tbjx,\'C\')(\'123\') # 2. 找到tbjx对象的C类,通过对C类这个对象使用反射取到area. print(getattr(tbjx.C,\'area\')) # 3. 找到tbjx对象的C类,实例化一个对象,对对象进行反射取值. obj = getattr(tbjx,\'C\')(\'张三\') print(obj.name) print(getattr(obj,\'name\'))
从当前模块应用反射
def func1(): print(\'in func1\') def func2(): print(\'in func2\') def func3(): print(\'in func3\') def func4(): print(\'in func4\') import sys print(sys.modules[__name__]) getattr(sys.modules[__name__],\'func1\')() getattr(sys.modules[__name__],\'func2\')() getattr(sys.modules[__name__],\'func3\')() # 本模块的模块名:sys.modules[__name__]
-
反射应用示例:
class User: def login(self): print(\'欢迎来到登录页面\') def register(self): print(\'欢迎来到注册页面\') def save(self): print(\'欢迎来到存储页面\') choose_dic = { 1: User.login, 2: User.register, 3: User.save, } while 1: choose = input(\'请输入序号: \\n1: 登录\\n2: 注册\\n3: 存储\').strip() obj = User() choose_dic[int(choose)](obj)
3. 函数与类的区别
-
函数都是显性传参,方法都是隐形传参
class A: @classmethod def func(cls,a): pass @staticmethod def func1(): pass A.func(666) A.func()
-
通过打印函数名的方式,区别什么是方法,什么是函数
def func1(): pass class A: def func(self): pass print(func1) print(A.func) obj = A() print(obj.func) # 结果: <function func1 at 0x000000A9C59C1EA0> <function A.func at 0x000000A9C75DE268> <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>
-
可以借助模块判断类中的是方法还是函数
from types import FunctionType from types import MethodType def func(): pass class A: def func(self): pass obj = A() print(isinstance(func,FunctionType)) # True print(isinstance(A.func,FunctionType)) # True print(isinstance(obj.func,FunctionType)) # False print(isinstance(obj.func,MethodType)) # True
4. 特殊的双下方法
-
特殊的双下方法: 原本是开发python这个语言的程序员用的.源码中使用的,双下方法: 你不知道你干了什么就触发某个双下方法
# 1.__len__ len(b)执行b类从属父类的__len__方法,必须要有return int(返回值) class B: def __init__(self,name,age): self.name = name self.age =age def __len__(self): return len(self.__dict__) # 2 b = B(\'张三\',28) print(len(b)) # 2.__hash__ hash()触发__hash__双下方法 class A(object): def __hash__(self): return 123456 obj = A() print(hash(obj)) # 3.__str__ 里边必须有return "字符串"类型 (优先级高于__repr__) # - 打印对象的时候,会触发__str__方法 # - str转化也可以触发 class A: def __init__(self,name,age): self.name = name self.age =age def __str__(self): print(\'触发str方法\') return f\'姓名: {self.name} 年龄: {self.age}\' a = A(\'张三\',35) # 打印对象触发__str__方法 print(f\'{a.name} {a.age}\') print(a) # 直接str转化也可以触发. print(str(a)) # 4.__repr__ 里边必须有return "字符串"类型 # - 打印对象的时候,会触发__repr__方法 class A: def __init__(self,name,age): self.name = name self.age =age def __repr__(self): print(666) return f\'姓名: {self.name} 年龄: {self.age}\' a = A(\'张三\',35) print(a) print(repr(a)) # 5.__call__ 对象()触发对象从属类(父类)的__call__方法 class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print(\'__call__\') obj = Foo() obj() # 6.__eq__ 两对象==时触发,return True/false(可以返回数字,字符串 一般返回布尔值) class A(object): def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): print(\'__eq__\') return True x = A() y = A() print(x == y) # 7.__del__ 析构方法 回收对象时触发__del__方法 class A: def __del__(self): print(\'__del__\') obj = A() del obj # 8.__new__ new一个对象(构造方法),实例化对象的时候会触发,对象是object类的__new__方法,产生了一个对象 class A(object): def __init__(self): print(\'in init function\') def __new__(cls, *args, **kwargs): print(\'in new function\') return object.__new__(A) # 对象是object类的__new__方法 产生了一个对象. a = A() # 类名() # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间. # 2. 执行__init__方法,给对象封装属性. # def __init__(self):(不能写返回值,因为__new__已经有返回值了,不能同时接收两个返回值,只能接收__new__的返回值) # 9.__item__系列(4个) # __getitem__ __setitem___ __delitem__ 对对象做类似于字典的(增删改查)触发__item__系列 class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): # print(item) # print(666) return self.__dict__[item] def __setitem__(self, key, value): # self.__dict__[key]=value print(key) print(value) def __delitem__(self, key): print(\'del obj[key]时,我执行\') f1=Foo(\'zhangsan\') f1[\'age\'] f1[1] = 2 del f1[1] # 10.__enter__ __exit__ with 上下文管理(2个) class A: def __init__(self, text): self.text = text def __enter__(self): # 开启上下文管理器对象时触发此方法 self.text = self.text + \'您来啦\' # 第一步 print(11111) return self # 必须!!!将实例化的对象返回f1 def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法 print(333) # 第三步 self.text = self.text + \',这就走啦\' with A(\'大爷\') as f1: print(2222) print(f1.text) # 第二步 print(f1.text) # 第四步 # 11.__iter__ for循环会触发此方法 class A: def __init__(self,name): self.name = name def __iter__(self): for i in range(10): yield i obj = A(\'张三\') for i in obj: print(i) # 12.__getattr__(self,item),__setattr__(self,key,value),__delattr__ # obj.属性会触发__getattr__(self,item)方法 # obj.属性=123 会触发__setattr__(self,key,value) # del obj.属性 就会触发__delattr__ 此方法
-
def func1(): pass class A: def func(self): pass print(func1) print(A.func) obj = A() print(obj.func) # 结果: <function func1 at 0x000000A9C59C1EA0> <function A.func at 0x000000A9C75DE268> <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>
以上是关于python 面向对象专题:元类type反射函数与类的区别特殊的双下方法的主要内容,如果未能解决你的问题,请参考以下文章