一 : 元类 type
- Type 获取对象从属的类
class A: pass print(type('abc')) # <class 'str'> print(type([1,2,3])) # <class 'list'> print(type((22,33))) # <class 'tuple'>
python 中一切皆对象,类在某种意义上也是一个对象,python 中自己定义的类,以及大部分内置类,都是由 type元类实例化得来的
type 与 object 的关系
object 是 type 类的一个实例
object 是type类的父类
print(issubclass(type,object)) # True
二 : 反射
程序对自己内部代码的一种自省
反射是什么?
通过字符串去操作对象的方式
四种使用场所
实例对象
类
本模块
其他模块
hasattr getattr setattr delattr
实例对象
hasattr : 判断是否存在,存在返回True,不存在返回 False
print(hasattr(obj,'name')) # True print(hasattr(obj,'country')) # True print(hasattr(obj,'func')) # True
getattr : 返回的是具体值,相当于取代那个万能的点
print(getattr(obj,'name')) # 赵海狗 print(getattr(obj,'country')) # 中国 print(getattr(obj,'func')) # <bound method A.func of <__main__.A object at 0x10a3d3b70>> print(getattr(obj,'func')()) 已经调用了这个函数了 # in A func # None print(getattr(obj,'sex',None)) # 指定查不到就返回 None print(getattr(obj,'sex')) # 报错
setattr : 相当于增加一个属性
setattr(obj,'sex','公') # 增加一个 print(obj.__dict__) # {'name': '赵海狗', 'age': 78, 'sex': '公'}
delattr : 删除一个属性
delattr(obj,'name') # 删除里面的值 print(obj.__dict__) {'age': 78, 'sex': '公'}
从类的角度
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,'country'): # print(getattr(A,'country')) # 中国 if hasattr(A,'func'): obj = A('赵海狗',26) getattr(obj,'func')() 在对象中调用,隐性传参 #<__main__.A object at 0x10966c240> 在函数中调用,显性传参 两种是一样的 # in A func getattr(A,'func')(obj) # <__main__.A object at 0x10966c240> # in A func
从其他模块
import tbjx (从其他文件导过来的) # 1.找到tbjx对象的C类,实例化一个对象 # print(getattr(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')) # 赵海狗
tbjx 文件如下 name = '太白金星' def func(): print('in tbjx func') class C: area = '北京' def __init__(self,name): self.name = name def func(self): print('in B func')
从当前模块研究反射
a = 666 def func(): print('in 本模块这个对象') def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') def func4(): print('in func4') # func1() # func2() # func3() # func4() import sys print(sys.modules[__name__]) # <module '__main__' from '/Users/zhl/Desktop/python_24/day26/课堂练习.py'> # 相当于一个字典 查找都有 print(getattr(sys.modules[__name__],'a')) # 666 func_lst = [f'func{i}' for i in range(1,5)] print(func_lst) for func in func_lst: getattr(sys.modules[__name__],func)() in func1 in func2 in func3 in func4
反射的应用
class User: user_list = [('login','登录'),('register','注册'),('save','存储')] def login(self): print('欢迎来到登录界面') def register(self): print('欢迎来到注册界面') def save(self): print('欢迎来到存储界面') while 1: choose = input('请输入序号:\n1:登录\n2:注册\n3:存储\n').strip() obj = User() getattr(obj,obj.user_list[int(choose) - 1][0])() # getattr(obj,'login) # 这样简化代码 显得更高大上一些
三 : 函数与方法的区别
通过打印函数名的方式区别什么是方法,什么是函数(了解)
def func1(): pass class A: def func(self): pass print(func1) print(A.func) # 通过类名调用的类中的实例方法叫做函数 obj = A() print(obj.func) # 通过对象调用类中的实例方法叫做方法
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 # 所以这个类名调用的类中的实例方法叫做函数 # 通过对象调用类中的实例方法叫做方法
总结 :
Python 中一切皆对象,类在某种意义上也是一个对象,Python 中自己定义的类
以及大部分内置类,都是由type 元类实例化而来
Python 中一切皆对象,函数在某种意义上也是一个对象,函数这个对象是从 FunctionType这个实例化出来的
Python 中一切皆对象,方法在某种意义上也是一个对象,方法这个对象是从 MethodType这个类实例化出来的
如何判断类中的是方法还是函数 ? ?
class A: @classmethod def func(cls,a): # 显性和隐性是从这里判断 pass @staticmethod def func1( ): pass A.func(222) # A.func() obj = A() obj.func('是') # 只要参数不对等,并且有 self cls 就是隐性传参 函数
四 : 特殊的双下方法
用途 : 原本是开发Python这个语言的程序员用的,源码中使用
str : 我们不能轻易使用,慎用
双下方法 : 不知道触发某个方法走下去
__len__
class B: def __init__(self,name,age): self.name = name self.age = age def __len__(self): print(self.__dict__) return len(self.__dict__) b = B('liye',28) # {'name': 'liye', 'age': 28} print(len(b)) # 2 print(len({'name':'liye','age':28})) # 2 字典的话就是键值对的个数 其他就是元素的个数
__str__ 用来返回字符串表达式
class A: def __init__(self,name,age): self.name = name self.age = age def __str__(self): print(666) return f'姓名:{self.name} 年龄:{self.age}' a = A('赵海狗',35) b = A('李业',33) c = A('华丽',18) # 打印对象触发 __str__ print(f'{a.name} {a.age}') # 赵海狗 35 print(f'{b.name} {b.age}') # 李业 33 print(f'{c.name} {c.age}') # 华丽 18 print(a) #666 # 姓名:赵海狗 年龄:35 print(b) print(c) print(str(a)) 直接 str 也可以触发 #666 # 姓名:赵海狗 年龄:35 打印了对象就触发了 str 所以是这个意思
__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) b = A('李业',12) c = A('华丽',18) print(a) print(repr(a)) # 666 # 姓名:赵海狗 年龄:35 # 666 # 姓名:赵海狗 年龄:35 # 两个结果是一样的 # 打印对象后也是触发 repr 吗? 他两有什么区别呢?和 str
print('我叫%s' % ('alex')) # 我叫alex print('我叫%r' % ('alex')) # 我叫'alex' print(repr('fdsaf')) # 'fdsaf' 看这个结果是把字符串啥的引号都给表现出来了
_call_
**对象() 自动触发对象从属于类(父类)的__call__方法**
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() obj() # __call__
_eq__
class A(object): def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True # return True x = A() y = A() print(x == y) # True 两种比较
__del__
class A: def __del__(self): print(666) obj = A() del obj # 666
_new_
class A(object): def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A) # object 342534 # # 对象是object类的__new__方法 产生了一个对象. a = A() #in new function in init function # 类名() # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间. # 2. 执行__init__方法,给对象封装属性. 我自己的理解是先执行 new 然后再执行 init
五 : python 中单例模式 重要必须会默写
class A: __instance = None def __init__(self,name): self.name = name def __new__(cls,*args,**kwargs): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance obj = A('alex') print(obj) obj1 = A('李业') print(obj1.name) print(obj.name) # <__main__.A object at 0x106e8cf28> # 李业 # 李业