Day19&20 python基础---面向对象进阶--装饰器函数,反射,内置方法

一,@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)

  

猜你喜欢

转载自www.cnblogs.com/lianyeah/p/9568530.html