Day 24~26 类,面向对象,属性
类:把一类事物的相同的特征和动作整合到一起就是类
对象:就是基于类而创建的一直具体的事物(具体存在的)也是特征和动作整合到一起
面向对象:
特征:
动作:
整合到一块
类,用”””类名+.”””取到
数据属性:即变量
函数属性:即函数
查看类的属性dir(类名)
--或-开头为系统内置的类
类名.__dict__[ ]: 查看类的属性字典
实例化
p1=Chinese(‘name’,’18’,’female’) #立即触发函数def __init__(self,参数)运行
#相当于p1=Chinese.__init__(p1,name,age,gender)
print(p1.__dict__)
类__init__(self,*args)__初始化函数不能用return函数,自动返回self,因为实例化自动return,会造成冲突,初始化函数用来帮类实例化出一个具体对象
def __init__(self,name,addr,type):
self.name=name #实质是self.key=value
实例能访问类属性,实例只有函数属性
类在调用自己的函数属性时,self参数为实例
School.func(p1)
函数属性命名建议定义:动词+名词:干什么事
类和实例的属性增删改查
实例调用class的方法时会自动传参,若实例自己调自己是不会自动传self参的
###不要修改底层的字典结构,如下代码,不可以这样写
p1.__dict__[‘sex’]=‘male’
print(p1.__dict__)
print(p1.sex)
#可以写p1.sex=‘male’
###特定程序写特定的功能的代码,不要混,会造成可读性差,输入输出不要写在函数里,函数只写逻辑,或者把输入输出单独做成函数
###在类中查找
类名.
p1.
在全局查找去掉”.”
在类中定义都在类的字典里,在init中定义都在实例的字典里
p1.l=“C” 在实例中
p1.l.append(‘C’) 在类中加
self表示和实例绑定
函数的静态属性
class Fuc:
@property #目的是调用时看不到内部的逻辑
def cal_area(self):
pass
r1.cal_area #调用数据属性
用类调用类方法
class Fuc:
@classmethod
def tell_info(cls,x):
pass
Fuc.tell_info(x)
静态方法
class Fuc:
@staticmethod #类的工具包,不能使用类变量和实例变量
def wash_body(a,b,c)#无self,不和具体实例绑定
pass
Fuc.wash_body(x,y,z)
###组合继承
类和类之间的关联
类的继承
代码之间越独立越好,尽量少做耦合
基类的方法不用实现,目的是规范子类
python3按广度优先查找
Func.__mro__ #查看类的继承顺序,经典类无此方法
super().__init__(父类的参数) #不用写父类,更更新父类名不会影响super()的逻辑
super().do() #不用写self,
###封装
__star#双下划线开头,自动重命名变为_类名__star
__star#双下划线开头默认和用户约定不能调用,隐藏的内部逻辑,但可以在类的内部调用
或可以在内部定义接口函数
def get_id(self): #访问函数
print(self.__star)
外部进行如下调用:
p1=get_id()
###反射
hasattr()#判断是否有该属性,返回True/False
func=getattr(p1,’类的属性名’,’如果没有该属性则打印此字符串里的内容’)#返回函数地址
func()
setattr(p1,’key’,’value’) #添加数据属性
setattr(p1,’func’,lambda self:self.name+’abc’) #添加函数属性
setattr(p1,’func’,lambda x:x+1) #添加函数属性
p1.func(10)
b1.func(b1)
delattr(p1,’key’) #del p1.key #删除属性
###动态导入模块
若模块名是字符串,t为m1文件夹下的模块
一般导入方式from m1 import t #相当于拼接路径m1/t
module_t=__import__(‘m1.t’) #拿到的是t
print(module_t)
>>> <module ‘m1’ (namespace)> #返回模块最顶层的文件夹
module_t.t.test1() #调用m1下t模块中的test1函数
_test2() #test2前加一个下划线,为私有,外部不能调用,但不是真正意义的限制,可以通过下面方法调用
from m1.t import _test2
或如下动态导入模块:
import importlib
m=importlib.import_module(‘m1.t’)
print(m)
m.test1()
m._test2()
###__getattr__() 很常用
1.当实例属性不存在时,会调用到类中的def __getattr__(self,item)
p1.aaaaaaaaaaaaaaaaa
2.删除类中的属性会调用到__delattr__(self,item)
del p1.x #触发__delattr__的运行,但并未真正执行删除操作,运用__delattr__可保护类里的属性不被删除
def __delattr__(self,item):
self.__dict__.pop(item) #即可删除相应属性
3.当设置类属性时会触发__setattr__(slef,key,value)的运行
def __setattr__(self,key,value):
self.__dict__[key]=value #若改为self.key=value会陷入死循环
f1.z=2
可用dir(类名)查看内置属性
print(f1.__dict__)
>>>{} #添加属性z=2发现列表为空,并没有执行真正的添加属性操作,需用self.__dict__[key]=value添加属性设置
class Foo:
def __getattr__(self,item):
print(‘你找到的属性%s不存在‘%item)
f1=Foo(‘xyy’)
print(f1.age) #f1,age对应self,item
>>>你找到的属性age不存在
###授权的关键点是覆盖__getattr__
class File:
def __init__(self,filename,mode=‘re’,encoding=‘utf-8’):
self.file=open(filename,mode,encoding=endcoing)
def __getattr__(self,item):
return getattr(self.file,item) #self.file,file为封装的函数
即使类里File无write,read的方法也可调用read,write