类的常用伎俩
- 隐藏数据属性和函数属性
隐藏类内属性是为了类体外访问不到相应的属性,为了保证数据安全以及简化接口的信息。类体内是可以正常访问的,也就是__name是类定义阶段就转换了,这种转换只是单纯语法上的转换。
隐藏对象的属性也是一样的情况
class Student:
__school="qinghua" #隐藏类中的数据属性
def __init__(self,name,age,gendar):
self.__name=name #隐藏对象中的数据属性
self.__age=age
self.__gendar=gendar
def __get_info(self): #隐藏类中的函数属性
print("%s的基本信息如下:" %(self.__name))
print("姓名:%s,年龄:%s,性别:%s" %(self.__name,self.__age,self.__gendar))
print(Student.__dict__["get_info"])
stu1=Student("lzz",28,"female")
print(stu1.__dict__)
print(stu1.gendar)
- property装饰器的使用
property装饰器主要是为了方便程序的使用者能够像调用数据一样来对函数进行查改删
class Student:
scheol="清华"
def __init__(self,name,age,gendat):
self.name=name
self.age=age
self.gendar=gendat
@property
def attr(self):
return print("my name is %s" %self.name)
@attr.setter
def attr(self,weight):
self.weight=weight
return "添加成功"
@attr.deleter
def attr(self):
del self.age
return "删除成功"
stu1=Student("lzz",90,"female")
# print(stu1.__dict__) # 注释的是原始方案(只添加@property)的调用方式
# print(stu1.tell_name())
# print(stu1.del_age())
# print(stu1.insert_weight("80kg"))
# print(stu1.__dict__)
stu1.attr #这个是统一命名了功能的名称后的调用方式
stu1.attr="30kg"
del stu1.attr
print(stu1.__dict__)
- classmethod和staticmethod装饰器使用
classmethod:一般定义的函数都是给对象使用的,类头上添加@classmethod会让该类定义的功能只能给类使用,不能通过该类生成对象
staticmethod:一定一个和静态类,该类和对象无关,可以传参数
类或对象的特性
封装
封装就是将数据和功能整合到一个容器中,在定义一个类的过程也就是封装的过程
继承(python支持多继承)
类是解决对象之间代码的冗余,而继承则是解决类和类之间代码的冗余
派生是继承了父类特性的子类。
多继承容易引发菱形问题,使用多继承容易引起的代码的逻辑混乱
python2中的继承分为:经典类(不是由内置类派生的子类),新式类(由内置类派生的子类);python3后都是新式类,默认继承了object类
class People:
country="china"
def __init__(self,name,age,gendar):
self.name=name
self.age=age
self.gendar=gendar
class Chinese(People):
def __init__(self,name,age,gendar,salary):
People.__init__(self,name,age,gendar)
self.salary = salary
obj1=Chinese("laa",25,"female",20000)
print(obj1.__dict__)
单继承和多继承的特点
单继承
1. 单继承可读性好,单继承属性的查找顺序(本身没有的属性到父类中查找),查找顺序参考mro属性,但是有时不可避免的使用多继承
多继承:
1. 多继承的可读性差,所以多继承正确的打开方式是mixins;
2. 菱形继承问题的属性查找问题:经典类–深度优先,新式类-广度优先。(菱形结构是指最终的基类非object类)
3. 非菱形继承的属性查找根据类的__mro__内置函数定义的顺序进行查找
class A:
def fun1(self):
print("from A")
def fun2(self):
print("from A2")
class B(A):
def fun3(self):
print("from B")
class C(A):
def fun4(self):
print("from C")
class D(B,C):
def fun4(self):
print("from D")
obj1=D()
print(D.__mro__)
子类派生的方法中重用父类的功能的两种方式
- 直接通过类名引用想用的功能,这个和继承没有关系
- 通过super()引用父类的功能,这个引用父类中功能的查找顺序按照mro。其中python2和3中的引用方式有区别
组合
将对象作为参数传给函数使用,使得对象中的属性也可以在函数中查找
多态和鸭子类型
一种事物的多种形态。符合:什么事物是什么事物;
把具有某种特征的事物就看作这种事物,这种归类叫做鸭子类型