初学者python笔记(封装、反射、类内置attr属性、包装与授权)

本文深入探讨了面向对象编程中的封装、反射、动态导入模块、类内置attr属性、包装与授权等高级概念,通过具体代码示例展示了这些概念的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本篇文章仍然是面向对象的相关内容,主要分析了封装、反射、动态导入模块、类内置attr属性、包装与授权三大面向对象编程的后续处理方法

封装

封装的本质:
把方法放到类里、把类放到模块里就叫装;

而其他地方导入模块、引用类、调用方法时看不到对应的模块、类、方法的具体逻辑,只知道名字就可以,因为它们是隐藏着的,这就叫封

封装的本质就要明确区分内外,因此封装是一种思想,内部就是内部,外部就是外部

class People:
    #以_开头的变量就是被隐藏的变量,外部使用它的时候就无法看到它
    _place= 'Beijing'
    __position= 'Python'
    def __init__(self,id_num,name,age,salary):
        self.id_num= id_num
        self.name= name
        self.age= age
        self.salary= salary

    def get_id(self):
        print('I am a privacy,我需要找的id为【%s】' %self.id_num)

#实例化
v1= People('12345678','Zoro',22,2000000)
print(v1._place)
#虽然被隐藏了,但是仍然可以调用它,隐藏只是一种约定,但python没有真正限制你去访问

#但是__开头的,就必须带上类名
#print(v1.__position)
print(v1._People__position

运行结果:
封装
真正效果上的封装: 明确区分内外,内部的实现逻辑,外部无法知道,并且为封装到内部的逻辑提供一个访问接口给外部使用

反射

反射的本质:
也叫做程序的自省,主要指程序可以访问、检测和修改它本身状态的一种能力

class BadGuy:
    feature= 'Ugly'  #特征是丑
    def __init__(self,name,address):  #两个参数,一个名字一个地址
        self.name = name
        self.address= address

    #动作(函数属性)
    def sell_house(self):
        print('【%s】 正在卖房子'%self.name)

    def rent_house(self):
        print('【%s】 正在租房子' %self.name)

#实例化
p1= BadGuy('黑中介','沙河')

#p1.sell_hourse()

#开始自我反省(反射)
print(hasattr(p1,'name'))  #对象中是否有name这个属性,返回值为布尔值
print(hasattr(p1,'sell_house'))
#hasattr()反射函数第一个参数为一个对象,第二个是字符串,相当于p1.name

print(getattr(p1,'name'))
#返回name这个属性对应的值(函数属性则返回函数内存地址),
#一参为对象,二参为字符串.若不存在,会报错
print(getattr(p1,'rent_house'))
#第三个参数为Default,表示若不存在则输出第三个参数
print(getattr(p1,'r_house','该属性不存在'))

setattr(p1,'新世界第五皇','路飞')  #在属性字典里新增一个键值对,也就是多一个属性
print(p1.__dict__)
#也可以增加函数属性
setattr(p1,'add_num',lambda x:x+1)  #自增1的匿名函数
setattr(p1,'join_str',lambda self:self.name+'是BadGuy')  #拼接字符串的匿名函数
print(p1.add_num(1313))  #调用函数
print(p1.join_str(p1))  #因为是以self为的匿名函数,所以传入的参数为对象名

delattr(p1,'新世界第五皇')  #删除属性字典里的键值对,一参为对象名,二参为键
print(p1.__dict__)

运行结果:
反射

动态导入模块

首先自定义一个简单的模块,放到web文件夹组成一个包:
自定义模块

#from web import test  #正常导入web包内的test自定义模块

#动态导入模块
module = __import__('web.test')  #导入相对路径下的web包内的test模块
print(module)  #其实导入的只是web包,整个module就代表了web,并没有test1
#这样操作才可以导入web下的test1
module.test.test1()  #导入并调用test1函数


#利用importlib模块来导入
import importlib
m = importlib.import_module('web.test')
print(m)  #与__module__不同,这里导入的就是test这个模块了
#因此可以直接调用
m.test2()  #就不用m.test.test2了

运行结果:
动态导入模块

类内置attr属性

总共有三大类内置attr属性:
getattr
setattr
delattr

class Test:
    y = 2020
    def __init__(self,x):
        self.x= x

    def __getattr__(self,item):  #item为必须参数
        print('正在执行__getattr__方法')

    def __delattr__(self,item):
        print('正在触发__delattr__操作')

    def __setattr__(self,key,value):  #设置值的时候是加入属性字典里,所以传入的是键值对
        print('正在用__setattr__设置值')
        #__setattr__内必须有设置值的操作
        self.__dict__[key]= value  #设置原属性字典

#实例化
p1= Test(520)

#__getattr__方法
print(p1.x)  #用属性字典来获取属性
print(getattr(p1,'__getattr__'))  #用getattr函数来获取属性
p1.jjjjjjjjjjjjjjjjjj  #一个不存在的属性名,就会触发__getattr__方法的执行

#__delatrr__方法
del p1.y  #当执行del操作时就会触发__delattr__方法的执行
#p1.__dict__.pop('x')  #这种方法不会触发__delattr__的执行


#__setattr__方法,当设置值的生活就会触发
print(p1.__dict__)  #输出原属性字典
p1.y= 13  #又设置两个新的键值对,就会执行两次__setattr__
p1.z= 14
print(p1.__dict__)

运行结果:
类内置attr属性
__getattr__的好处:
当传入不存在的属性时不会报错,而是输出对应的提醒

class Test:
    y = 2020
    def __init__(self,x):
        self.x= x

    def __getattr__(self,item):  #item为必须参数
        print('你找的属性【%s】不存在!' %item)  #此时的item就是调用时传入的属性


#实例化
p1= Test(520)

#__getattr__方法
print(p1.x)  #用属性字典来获取属性
print(getattr(p1,'__getattr__'))  #用getattr函数来获取属性
p1.jjjjjjjjjjjjjjjjjj  #一个不存在的属性名,就会触发__getattr__方法的执行

运行结果:
__getattr__的好处

包装与授权

包装: 包装一个类型通常是对已经存在的类型进行一些定制,可以新建、修改、删除原有产品的功能,其他的保持原样

授权: 授权是包装的一个特性,所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性;实现授权的关键点就是覆盖__getattr__方法

import time  #导入时间模块

class Open:  #产生一个文件的类
    def __init__(self,filename,mode,encoding):
        #self.filename= filename
        #打开一个文件并设为self.file属性
        self.file= open(filename,mode,encoding=encoding)
        self.mode= mode
        self.encoding= encoding

    #一个中转站
    def __getattr__(self,item):
        print('【%s】不存在!' %item)
        print(item,type(item))  #输出传入值和它的类型

        #授权的实现
        return getattr(self.file, item)
        #获取self.file中的信息,不存在就会新建一个,并返回新建方法的内存地址

    #覆盖__getattr__方法,即自定义一个write的方法,就表示已经存在了write方法,
    #所以不会触发__getattr__方法去新建一个write方法
    def write(self,line):  #第二个参数是传入的写的内容
        t = time.strftime('%Y-%m-%d %t')  #字符格式化显示系统时间,年-月-日
        self.file.write(t + line)  #字符串拼接

#实例化及调用
p1= Open('a.txt','r+','gbk')
print(p1.file)  #输出file的信息

p1.read  #触发__getattr__,运行getattr()方法
#新建了一个item的方法,就可以调用到了
print(p1.write)  #再次触发__getattr__,使其新建一个write的方法

#就可以实现写的操作了
p1.write('Is ok...\n')
p1.write('终于可以写进来了\n')

p1.file.close()  #关闭文件,实现数据的更新

运行结果:
包装与授权
在文件中也正常写入了内容:
授权

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸿蒙Next

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值