1.函数与方法的判断
1.1 通过打印类名的方式
class A:
def func(self):
pass
def func():
pass
print(A.func) <function A.func at 0x000001ED27190BF8>
print(func) <function func at 0x0000028B166C2EA0>
obj = A()
print(obj.func) <bound method A.func of <__main__.A object at 0x0000028B1689E9E8>>
1.2 借助FunctionType,MethodType
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,MethodType)) # True,方法
1.3 类中的实例方法:
如果通过类名调用,就是FunctionType
如果通过实力调用,就是MethodType
类中的类方法:
类中的类方法: 是方法MethodType
类中的静态方法: 是函数FunctionType
1.4 方法和函数的区别
函数显性传参,不依赖于对象
方法是隐性传参,要依赖对象,类
2.类的约束
制定了一个强制的标准,强制子类要有父类规定的方法(并没有做到强制的规范,如果不继承,约束就没用)
2.1 raise Exception(),主动报错,在父类的方法中主动抛出异常
class Payment:
def pay(self,money):
raise Exception('子类要定义pay方法!!!')
class Alipay(Payment):
def pay(self,money):
print('使用阿里支付了%s元'% money)
class QQpay(payment):
def pay(self,money):
print('使用QQ支付了%s元'% money)
class WeChatpay(self,money):
def zhifu(self,money):
print('使用微信支付了%s钱'% money)
def pay(self,money): ***** 统一了支付方式,归一化设计
obj.pay(money)
obj1 = Alipay()
obj2 = WeChatpay()
obj1.pay(10)
obj2.pay(10)
2.2 引用抽象类,接口类;子类实例化对象时没有这个方法就报错
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类 @abstractmethod def pay(self): pass # 抽象方法 class Alipay(Payment): def pay(self,money): print('使用支付宝支付了%s元'%money) class WeChat(Payment): def zhifu(self,money): print('使用微信支付了%s元'%money) def pay(a,money): a.pay(money)
ali = Alipay() ali.pay(100) pay(ali,money) # 归一化设计,不管是哪一个类的对象,都调用同一个函数完成相似功能
we = Wechat() we.zhifu() # 用的时候就会报错
pay(we,100)
3.类的成员
3.1类方法(使用装饰器@classmethod)
主动接收类名,与类的静态属性相关,与对象无关的需求,需要使用类方法
类名.类方法 对象.类方法, 传给cls的都是类空间
设置一个场景: 计算班级学生人数
class Student:
stu_num = 0
def __init__(self,name,age):
self.name = name
self.age = age
Student.add_num()
@classmethod
def add_num(cls):
cls.stu_num += 1
def get_num(self):
return cls.stu_num
ali = Student('阿狸',6)
tuan = Student('团子',5)
print(Student.get_num()) 结果为2
3.2静态方法(使用装饰器@staticmethod)
静态方法不依赖于对象和类,但是为了保持代码的一致性和整体性,可以将其设置为静态方法,是一个独立的,单纯的函数
设定一个场景,时间操作,其中有一个获取当前时间的函数
import time
class Timetest:
def __init__(self,hour,minute,second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def showTime():
return time.strftime('%H:%M:%S',time.localtime())
print(Timetest.showTime)
t = Timetest(2,10,10)
now_time = t.showTime()
print(now_time)
3.3属性(使用装饰器@property)
用的最多,也见的最多
写法一:
class A:
def __init__(self)
pass
@property
def AAA(self):
print('执行的时候执行')
@AAA.setter
def AAA(self):
print('修改的时候执行')
@AAA.deleter
def AAA(self):
print('删除的时候执行')
f1 = A()
f1.AAA
f1.AAA = 'aaa'
del f1.AAA
写法二:
class Foo:
def get_aa(self):
print('')
def set_aa(self):
print('')
def del_aa(self):
print('')
aa = property(get_aa,set_aa,del_aa)
f1 = Foo()
f1.aa
f1.aa = 'aaa'
del f1.aa
3.4特殊的双下方法
双下方法是解释器提供的由 __方法名__的具有特殊意义的方法,主要是python源码程序员使用,深入的研究双下方法,会更便于阅读源码.不同的双下方法有不同的触发方式
__init__,实例化对象时,就执行__init__方法
__len__
class A:
def __len__(self):
print(666)
a = A()
len(a) # 只要len一个实例化对象,就会出发__len__方法
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
__hash__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a)) # 随机生成一个哈希值,hash一个实例化对象就调用
__str__
class A:
def __str__(self):
return '123' return后面不能是 int 类型
a = A()
print(a)
print('%s'%a) # 打印对象时,默认输出该方法的返回值
__repr__
class A:
def __repr__(self):
return '太白'
a = A()
print(repr(a))
print('%r'%a) # repr(对象)时,默认输出该方法的返回值
__call__
class A: def __call__(self,*args,**kwargs): print('__call__') a = A() a()
A()() # 对象+()触发执行__call__方法,或是类名()()
__eq__
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
a = A()
b = B()
print(a==b) # 比较两个实例化对象时触发
__new__构造方法
class A:
def __init__(self):
self.x = 1
print('in init')
def __new__(cls,*args,**kwargs):
print('in new')
return object.__new__(A,*args,**kwargs)
a = A()
print(a.x)
单例模式:一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例,且该实例易于被外界访问,从而可以节约系统资源,控制实例个数
class A:
def __new__(cls,*args,**kwargs):
if cls.a is None:
obj = object.__new__(cls)
cls.a = obj
return cls.a
__item__
class A:
def __init__(self,name):
self.name = name
def __getitem__(self,item):
print('self.__dict__[item]')
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
a = A()
a['age'] = 18 # 自动触发__setitem__
del a['age'] # 触发__delitem__
a['name'] = 'alex' # 自动触发__setitem__
print(a.__dict__)
__enter__和__exit__: 上下文管理
class A:
def __init__(self, text):
self.text = text
def __enter__(self): # 开启上下文管理器对象时触发此方法
self.text = self.text + '您来啦'
return self # 将实例化的对象返回f1
def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法
self.text = self.text + '这就走啦'
with A('大爷') as f1:
print(f1.text)
print(f1.text)
4.反射: 通过字符串对实例化对象进行相应操作
hasattr,检测是否含有某种属性, getattr,获取某个属性
setattr,设置某个属性, delattr,删除某个属性
01. 对对象进行反射
class A:
def __init__(self,name,age):
self.name = name
self.age = age
obj = A('小胖',18)
print(hasattr(obj, 'name'))
print(getattr(obj, 'age'))
setattr(obj,'sex','男')
print(obj.__dict__) # {'name':'小胖','age':18,'sex':'男'}
delattr(obj,'age')
print(obj.__dict__) # {'name':'小胖','sex':'男'}
02. 对类的反射
class A:
country = '中国'
def __init__(self):
self.name = '小胖'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print(getattr(A,'country')) # 中国
print(getattr(A,'func')) 方法名内存# <function A.func at 0x000002BE2ABA0C80>
print(getattr(A,'bar')) # <function A.bar at 0X000002BE2ABD8048>
03. 当前模块的反射
import sys
def foo():
print('in foo')
def func():
print('in func')
module = sys.modules[__name__]
print(hasattr(module,'foo')) # True
getattr(module,'func') # in func
04. 其他模块的反射
import 另一个模块名
print(hasattr(模块名, 方法名或属性名))
foo = getattr(模块名, 属性名)
print(foo) 属性值
ret = getattr(模块名,方法名)
ret() # 调用另一个模块的方法
5.isinstance和issubclass
isinstance: 判断对象是否为类的实例化对象
class A:
pass
class B(A):
pass
obj = B()
print(isinstance(obj,B))
issubclass: 判断此类是否为另一个类的派生类
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(B,A))
print(issubclass(C,A))