一,@property装饰器:将一个方法伪装成属性
1、一个方法为伪装成属性之后
2、应该可以执行一个属性的增删改查操作
3、那么增加和修改,就对应被@setter装饰的方法:这个方法有一个必传的参数new,表示赋值的时候等号后面的值
4、删除一个属性 对应着 被@deleter装饰的方法,这个方法并不能在执行的时候真的删除这个属性,而是你在代码中执行什么就有什么效果
class Goods: __discount = 0.8 #折扣 def __init__(self,price): self.__price = price self.name = 'apple' @property # 只有当被property装饰的方法 def price(self): return self.__price * Goods.__discount @price.settter # 且被setter装饰器装饰了 def price(self,new) # 又实现了一个同名方法 self.__price = new #可以用来保护一个变量 在修改的时候能够添加一些保护条件 @price.deleter #删除一个property属性的时候会执行被deleter装饰的方法 def price(self) del self.__price apple = Goods(10) print(apple.price) print(apple.__dict__) del apple.price apple.price = 8 # 且 在 对被装饰的方法 赋值的时候 就出发被setter装饰器装饰的方法 print(apple.price) print(apple.__dict__) del apple.name print(apple.__dict__)
二,@classmethod装饰器:在类中定义一个类方法
类方法的特点:只使用类中的资源,且这个资源可以直接用类名引用形式地使用,那这个方法应该被改为一个类方法
类方法的默认参数:cls指的时调用这个方法的类
类方法的调用方式:通过类名调用,本质是方法
Q:什么时候用?
如果整个方法中都没有用到对象命名空间中的名字,且你用到了类的命名空间的名字(普通的方法和property方法除外)
class Goods: __discount = 0.8 #静态属性 def __init__(self,price): self.__price = price #对象属性 self.name = 'apple' @property def price(self): # print(self) return self.__price * Goods.__discount @classmethod def change_discount(cls,new): #类方法 cls.__discount = new g1 = Goods(10) print(g1.price) Goods.change_discount(0.7) print(g1.price) # print(Goods.__dict__)
三,@staticmethod装饰器 :在类中定义一个函数,这个函数被称为静态方法
静态方法的特点:
将一个普通的函数放到类中来就给这个函数加上一个@staticmethod装饰器
这个函数不需要传默认的参数:self,cls
静态方法的调用方式:通过类名调用,本质还是函数
class Foo: @classmethod def class_method(cls):pass @staticmethod def static_method():pass from types import MethodType,FunctionType obj = Foo() print(isinstance(Foo.class_method,MethodType)) print(isinstance(Foo.static_method,FunctionType)) #是一个函数 print(obj.static_method) #<function Foo.static_method at 0x000002D06E725EA0>
四,类内属性总结:
静态属性:
所有对象都统一拥有的属性
一般被类调用
类方法:
如果这个方法涉及到操作静态属性、类方法、静态方法
默认参数:cls,表示类
一般被类调用
静态方法:
不使用类中或普通方法中的的命名空间也不适用对象的命名空间 : 一个普通的函数方法
没有默认蚕食
一般被类调用
方法:
普通方法
默认参数:self,表示对象
一般被对象调用
property方法:
默认参数:self,表示对象
一般被对象调用
五,isinstance & issubclass
isinstance:判断对象和类之间的关系
特点:判断这个对象是否是这个类、这个类的子类的对象
issubclass:判断类和类之间的关系
特点:判断一个类是否是另一个类的子类
#检测对象与类之间的关系
class A:pass class B(A):pass a = A() b = B() print(type(a) is A) print(type(b) is B) print(type(b) is A) print(isinstance(a,A)) print(isinstance(b,A)) print(isinstance(a,B)) print(type(123) is int) #对比 print(isinstance(123,int))
#检测类与类之间的关系 class A:pass class B(A):pass print(issubclass(A,B)) print(issubclass(B,A))
六,反射
Q1:什么是反射
使用字符串数据类型的变量名来获取这个变量的值
Q2:为什么需要反射(三个场景)
#input:
#用户输入的如果是a,那么就打印1,如果输入的是b就打印2,如果输入的时name,就打印alex
#文件
#从文件中读出的字符串,想转换成变量的名字
#网络
#将网络传输的字符串转换成变量的名字
Q3:反射的用法与应用
getattr和hasattr方法解析:
getattr(变量名:命名空间,字符串:属于一个命名空间内的变量名),如果该变量存在于这个命名空间,则返回该变量名,否则报错
hasattr(变量名:命名空间,字符串:属于一个命名空间内的变量名),如果该变量存在于这个命名空间,则返回True,否则返回False
#反射类中的变量:静态属性,类方法,静态方法
#反射类中的变量:静态属性,类方法,静态方法
class Foo: School = 'oldboy' Country = 'China' language = 'Chinese' @classmethod def class_method(cls): print(cls.School) @staticmethod def static_method(): print('in staticmethod') def func(self): print(666) print(Foo.School) print(Foo.Country) print(Foo.language) #输入属性名并打印 #判断实现 inp = input('>>>').strip() if inp == 'School':print(Foo.School) elif inp == 'Country':print(Foo.Country) elif inp == 'language':print(Foo.language) #反射实现 while 1: inp = input('>>>').strip() print(getattr(Foo,inp))
getattr(Foo,'School') #Foo.School print(Foo.class_method) print(getattr(Foo,'class_method')) getattr(Foo,'class_method')() #Foo.class_method() getattr(Foo,'static_method')() #Foo.static_method() getattr(Foo,'func')(1) #Foo.func(1) #检测类中是否有此静态属性名或方法名 print(hasattr(Foo,'func')) print(hasattr(Foo,'fu')) #反射实现: while 1: inp = input('>>>').strip() if hasattr(Foo,inp): print(getattr(Foo,inp))
#反射对象中的变量
#反射对象中的变量(对象属性,普通方法)
class Foo: def __init__(self,name,age): self.name = name self.age = age def eating(self): print('%s is eating'%self.name) alex = Foo('alex',33) print(getattr(alex,'name')) print(getattr(alex,'age')) getattr(alex,'eating')()
#反射模块中的变量
#反射模块中的变量 import os os.rename('xx.py') getattr(os,'rename')('xx.py')
#反射本文件中的变量
# 反射本文件中的变量 a = 1 b = 2 name = 'alex' def func(): print('func') class Foo:pass import sys print(sys.modules['__main__']) # 本文件的命名空间 print(sys.modules) # 查看所有文件的命名空间 print(sys.modules['__main__'].a) #查看本文件的命名空间中a的值 # __name__变量,内置的变量__name__等于'__main__' print(sys.modules[__name__]) #反射本文件中变量 固定的使用这个命名空间 print(getattr(sys.modules[__name__],'a')) print(getattr(sys.modules[__name__],'b')) print(getattr(sys.modules[__name__],'name')) getattr(sys.modules[__name__],'func')() print(getattr(sys.modules[__name__],'Foo')) obj = getattr(sys.modules[__name__],'Foo')() print(obj)
setattr(变量名:命名空间,字符串:属于一个命名空间内的变量名,变量值),如果该变量名存在于这个命名空间,则修改该变量对应的值,否则增加这个属性
delattr(变量名:命名空间,字符串:属于一个命名空间内的变量名),如果该变量存在于这个命名空间,则执行删除操作,否则报错
#setattr
class Foo: Country = 'China' def func(): print(666) setattr(Foo,'School','OLDBOY') # 接受三个参数 命名空间 ‘变量名’ 变量值 print(getattr(Foo,'School')) setattr(Foo,'School','OLDLADY') print(Foo.School) setattr(Foo,'func',func) # 一般没人往空间中添加函数 print(Foo.__dict__) # 'func': <function func at 0x000001D657AF5E18> Foo.func()
#delattr del Foo.Country print(Foo.__dict__) delattr(Foo,'Country') print(Foo.__dict__)
七,内置方法
在不是需要程序员定义,本身就存在在类中的方法就是内置方法
内置方法的结构:__名字__
通称:双下方法,魔术方法,内置方法
所有的双下方法都不需要我们直接去调用,都有另外一种自动触发它的语法
#__init__:
不需要我们主动调用,而是在实例化的时候内部自动调用的
#__str__ :
当你打印一个对象的时候,触发__str__
当你使用%s格式化的时候,触发__str__
str强转数据类型的时候,触发__str__
#__repr__:
repr是str的备胎
有__str__的时候执行__str__,没有实现__str__的时候,执行__repr__
repr(obj)内置函数对应的结果是__repr__的返回值
当你使用%r格式化的时候,触发__repr__
class Course: def __init__(self,name,period,price,teacher): self.name = name self.period = period self.price = price self.teacher = teacher def __str__(self): return 'str: %s %s %s %s' % (self.name,self.period,self.price,self.teacher) def __repr__(self): return 'repr: %s %s %s %s' % (self.name, self.period, self.price, self.teacher) course_lst = [] python = Course('python','6 month',29800,'oldboy') course_lst.append(python) linux = Course('linux','5 month',25800,'oldboy') course_lst.append(linux) for id,course in enumerate(course_lst,1): print(id,course) print('%s %s'%(id,course)) print(str(course)) print(repr(course)) print('%r'%course)
#继承关系中的__str__和__repr__寻找顺序 class Foo: def __str__(self): #2 return 'Foo.str' def __repr__(self): #4 return 'Foo.repr' class Son(Foo): def __str__(self): #1 return 'Son.str' def __repr__(self): #3 return 'Son.repr' s1 = Son() print(s1)