Day27 of learning python--反射和部分双下方法

一、面向对象的复习

命名空间:类和对象分别存在不同的命名空间中,对象能找到类的,类找不到对象的。

继承:super 只能在python3中使用,super是根据mro广度优先顺序找上一个类的。

封装:私有的,只能在类的内部调用,子类都无法继承

多态:鸭子类型

3个装饰器:

@property  伪装成一个静态属性,会使用@name.setter

@staticmethod 在面向对象程序中,如果一个函数,既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数变成一个静态方法。类方法和静态方法都是类调用,对象也同样可以调用类方法和静态方法,静态方法没有默认参数。

@classmethod 当一个方法只使用了类的静态变量时,就给这个方法加上@classmethod装饰器,默认传cls参数,就是修改类的静态属性,在调用修改这个属性时,就是整个改变这个属性值

1 class Goods:
2     __discount = 0.8
3     @classmethod
4     def change_discount(cls):
5         cls.__discount =0.5
6     
7 Good.change_discount()

组合:

class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

class Classes:
    def __init__(self,name):
        self.name = name
        self.course = python.name  # 在第一次定义的时候,就已经是写死了,后面python的改变,而不会影响到此改变的

python = Course('python',19800,'6 months')
pys9 = Classes('python_s9')
print(pys9.course)
# print(pys9.course.name)
python.name = 'python全栈'
print(pys9.course)
# print(pys9.course.name)

二、isinstance 和 issubclass

isinstance(obj,cls)检查obj是否是cls的对象

1 class A:pass
2 a = A()
3 print(isinstance(a,A))

issubclass(sub,super)检查sub类是否是super类的派生类

class A:pass
class B(A):pass
print(issubclass(B,A))

三、反射

python面向对象中的反射:通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)

getattr的使用

1.反射类对象中的属性&方法

class A:
    def func(self):
        print('in func')

a = A()
a.name = 'alex'
a.age = 84
#反射对象的属性
ret = getattr(a,'name')  # 通过变量名的字符串形式取值
print(ret)
# 变量名= input('>>>')
# print(getattr(a,变量名))
# print(a.__dict__[变量名])

# 反射方法
# a.func()
ret = getattr(a,'func')  #绑定一个方法的地址
ret()
对象的属性&方法

2.反射类的属性&方法

class A:
    price = 20
    @classmethod
    def func(self):
        print('in func')
# 反射类的属性
# A.price
print(getattr(A,'price'))
# 反射类的方法:classmethod staticmethod
# A.func([])
A.func()
if hasattr(A,'func'):
    ret = getattr(A,'func')()
类的属性&方法

3.反射模块的属性&方法

#my.py
day = 'Monday'  # 周一
def wahaha():
    print('wahaha')

import my
# 反射模块的属性
# print(my.day)
print(getattr(my,'day'))
#反射模块的函数
getattr(my,'wahaha')()
模块的属性和方法

4.反射模块中类

#my.py
class C:
    pass

import my
print(getattr(my,'C')())  #  加括号就是实例化一个对象
模块中的类

5.反射内置模块中的方法

import time
print(getattr(time,'time')())
print(getattr(time,'asctime')())

# 要反射的函数有参数怎么办?
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:%S'))
结果:
1542188398.019721
Wed Nov 14 17:39:58 2018
2018-11-14 17:39:58
2018-11-14 17:39:58
内置模块中的方法

6.反射自己模块中的变量&方法

def qqxing():
    print('qqxing')
year = 2018
import sys
#print(sys.modules['__main__'].year)

#反射自己模块中的变量
# print(getattr(sys.modules['__main__'],'year'))

# 反射自己模块中方法
# getattr(sys.modules['__main__'],'qqxing')()
变量名 = input('>>>')
print(getattr(sys.modules[__name__],变量名))
自己模块中的变量&方法

注意:由于这个模块可能被其他模块调用,所有要把‘__main__'写成__name__,这样就不会写死了,否则在其他模块中,不能调用自己的模块的变量和方法

setattr的使用

用来修改变量

class A:
    pass
a = A()
setattr(A,'name','alex')
setattr(a,'name','naza')
print(A.name)
print(a.name)
结果:
alex
naza

delattr的使用

删除变量

class A:
    pass
a = A()
setattr(A,'name','alex')
setattr(a,'name','naza')

delattr(a,'name')
print(a.name)  #对象找不到,找类中的
delattr(A,'name')
# print(A.name)
结果:
alex

hasattr的使用

判断是否有这个变量,一般和getaattr搭配着使用

class Foo:
    f = '类的静态变量'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def say_hi(self):
        print('hi,%s'%self.name)

obj=Foo('egon',73)

#检测是否含有某属性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))

四、类的双下方法

print(1,'1')
print(repr(1))
print(repr('1'))
结果:
1 1
1
'1'

__str__的使用

class A:
    def __str__(self):
        return "A's object"
    def func(self):
        return 'wahaha'
a = A()
print(a)   # 打印一个对象的时候,就是调用a.__str__
#a.__str__  -- > object
结果:
A's object
注意:对象的基类是object ,这里面有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
# l = [1,2,3,4,5] #实例化,实例化了一个列表类的对象
#print(l)  # 此处重定制了
print('%s:%s'%('A',a))  # %s str() 直接打印,实际上都是走的__str__

print(obj)/'%s'%obj/str(obj)的时候,实际上内部调用了obj.__str__方法,如果str方法有,那么他就返回的必定是一个字符串

__repr__的使用

class A:
    def __repr__(self):
        return "A's object"
    def func(self):
        return 'wahaha'

a = A()
print(repr(a))
print('%s:%r'%('a',a)
结果:
A's object
a:A's object

注意:%r repr() 实际走的都是__repr__,repr 是str的备胎,如果使用str()时没有找到__str__()的这个方法,则会去找__repr__()。

__del__的使用

class A:
    def __del__(self):
        self.f.close()  #所以在此处删除时,则做一些收尾工作,把文件关闭
        print('执行我啦!')

a = A()
a.f = open()  # 打开文件,第一在操作系统中打开了一个文件,拿到了文件操作符在内存中
del a   # a.f 拿到的文件操作符消失在了内存中,但是没有把文件关闭
import time
time.sleep(3)
# del a   # del 即执行了这个方法,有删除了这个这个对象
# print(a)
#引用计数,自动计算,为O时删除变量

__call__的使用

class A:
    def __init__(self,name):
        self.name = name
    def __call__(self):
        '''
        打印这个对象中的所有属性
        :return:
        '''
        for k in self.__dict__:
            print(k,self.__dict__[k])

a = A('alex')
a()
#相当于a =  A('alex')(),直接使用对象加括号,调用__call__方法
posted on 2018-11-14 18:07  smile大豆芽  阅读(130)  评论(0)    收藏  举报