Python 小栈_20:Python 面向对象类的反射函数以及包装标准类型

今日学习:

 

一、动态导入模块

1、若模块名不是字符串,可以直接用import或from ... import ...导入模块

2、若模块名为字符串,则可以使用__import__(“字符串命名”)

m=__import__("1.text")    #可导入字符串命名的,且不管多少层,只是调用最顶层的模块,即只调到1这一层
print(m)

print(m.text.test(1,2))    #所以在调用时还得输入1之后的内容,以m.text.函数名再去调用

3、导入动态模块(importlib)

import importlib
m=importlib.import_module("1.text")      #注意在调用impotr_module 时,参数要用字符串形式
print(m)
print(m.test(1,2))


>>>
<module '1.text' from 'D:\\PyCharm 2019.3.3\\python_s1\\面向对象\\1\\text.py'>   #m为导入模块的路径
3

 

二、__setattr__、__getattr__、__delattr__

1、__getattr__()   #只有在属性不存在时才会触发该函数运行

# __getattr__()函数在类中用来获取属性,若没有该属性在会运行__getattr__()函数
class F:
    def __init__(self,y):
        self.y=y

    def __getattr__(self, item):
        print("我是来自__getattr")


f1=F(10)
print(f1.y)     #有y属性,则返回y的值
print(f1.xxyy)   #没有该属性,调用__getattr__()函数


>>>
10
我是来自__getattr
None

2、__setattr__()

#只要是在设置属性时(包括修改和添加)时会触发__setattr__函数运行
class F:
    def __init__(self,y):
        self.y=y
    def __setattr__(self, key, value):
        # self.key=value     #不可以。若直接这样写会有一个死循环,一直在重复设置属性
        self.__dict__[key]=value     #可以。设置属性实际上就是在添加一个属性到其属性字典里面
f1=F(10)
f1.test="abc"
print(f1.__dict__)


>>>
{'y': 10}
{'y': 10, 'test': 'abc'}

3、__delattr__()

# 只要是删除操作,就会触发__delattr__()函数运行
class F:
    def __init__(self,y):
        self.y=y

    def __delattr__(self, item):
        print("我是删除操作的")
        # del self.item      #这种就无限递归了,不可取
        self.__dict__.pop(item)      #这种直接在底层进行删除,不会陷入递归

f1=F(10)
del f1.y
# del f1.x
print(f1.__dict__)


>>>
我是删除操作的
{}

 

三、包装标准类型

包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)

1、继承加派生(可定制属性,把父类中的属性都继承下来)

 

class List(list): #list也是一个类。会继承list所有的属性,也可以派生出自己新的,比如append和mid
    def append(self, p_object):
        if type(p_object) is int:
            #self.append(p_object)    这种会无限递归
            super().append(p_object)
            list.append(self,p_object)  #这两种方式都可以调用父类的属性(用super不用传入self)
            
        else:
            pass



l=List([1,2,3,4])
print(l)
l.append(5)     #调用append方法
print(l)
# l.append('1111111') #报错,必须为int类型


>>>
[1, 2, 3, 4]
[1, 2, 3, 4, 5]

 

 

2、授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

(通过__getattr__方法来实现)

import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        '''
        self.filename=filename
        self.mode=mode
        self.encoding=encoding
        '''

        self.file=open(filename,mode,encoding=encoding)     #可用这种组合的方式代替上面三种
    # def write(self,line):                     #若在这里有定义write属性,则会调用该属性
    #     t=time.strftime('%Y-%m-%d %X')
    #     self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):             #并没有write的属性,这时会调用到__getattr__函数
        return getattr(self.file,item)

f1=FileHandle('b.txt','w+')
f1.write('你好啊')      #触发__getattr__运行  f1会传给self,write会传给item
f1.seek(0)
print(f1.read())
f1.close()



>>>
你好啊

 

以上。

posted @ 2020-03-25 21:52  七七)  阅读(132)  评论(0)    收藏  举报