组合、多态、内置方法、反射
一、组合
1、 组合就是将另一个类的对象赋值给当前对象的属性
对象表示一种“有”’的关系
继承表示一种“是”的关系
class People:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Teacher:
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level
def tell(self):
print("%s:%s" % (self.name, self.age))
class Student:
def __init__(self, name, age, gender):
super().__init__(name, age, gender)
class Course:
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
def tell(self):
print('<%s:%s:%s>' % (self.name, self.price, self.period))
tea1 = Teacher("egon", 20, "male", 10)
stu1 = Student("cc", 18, "male")
python = Course("python开发", 30000, "3mons")
linux = Course("linux课程", 30000, "3mons")
tea1.courses = [python,linux]
stu1.course = python
此时对象teacher1集对象独有的属性、Teacher类中的内容、Course类中的内容于一身(都可以访问到),是一个高度整合的产物——超级对象
二、多态
2.1 多态性
同一种事物有多种形态,(如动物类有人类、鸟类、爬行动物类等多种类)
我们可以在不考虑某一种对象的具体类型的前提下,直接使用该对象
即:父类有的功能,子类一定有
class Animal: #同一类事物:动物
def talk(self):
pass
class Cat(Animal): #动物的形态之一:猫
def talk(self):
print('喵喵喵')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('汪汪汪')
class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('哼哼哼')
cat = Cat()
dog = Dog()
pig = Pig()
cat.talk() # 喵喵喵
dog.talk() # 汪汪汪
pig.talk() # 哼哼哼
更进一步,我们可以设置一个统一的接口来使用
def talk(animal):
animal.talk()
talk(cat)
talk(dog)
talk(pig)
python中一切皆对象,本身就支持多态性
# 我们可以在不考虑三者类型的情况下直接使用统计三个对象的长度
s.__len__()
l.__len__()
t.__len__()
# Python内置了一个统一的接口
len(s)
len(l)
len(t)
2.2 metaclass方法
多态性的本质就是不同的子类中定义有相同的方法名,这样我们就可以不考虑类而统一使用一种方式去使用对象,
可以在父类中引入抽象类的方法来限制子类中必须有某些方法名
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
def talk(self):
pass
cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
Animal 类的作用就是相当于一个标准,它不能被实例化
2.3 总结
使用多态性的好处:
1.增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
2.增加了程序额可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
2.4 鸭子类型
python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象
也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。
三、一切皆对象
在python3中,
数据类型==类
print(int) # <class 'int'>
如内置的list:
x = [1, 2, 3] # list([1,2,3]) x就是类list实例化的对象
x.append(4) # 等同于list.append(x,4), 调用的是list类的方法list.append(self, __object)
四、内置函数
4.1 isinstance(obj, cls)
检查obj是否是类cls的对象
print(isinstance(10, int)) # True
4.2 issubclass(sub, super)
检查sub类是否是super类的派生类
class People:
pass
class Student(People):
pass
print(issubclass(Student, People)) # True
五、内置方法
内置方法都是在满足某种条件自动调用的,
5.1 str
用于改变对象的字符串显示
返回值必须是字符串
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"姓名:{self.name} 年龄:{self.age}"
p1 = People('cc', 18)
print(p1) # 姓名:cc 年龄:18
5.2 del
构析方法,用于当对象在内存中被释放时,自动触发运行
ps:
如果产生的对象只是python语言级别的,那么无序定义__del__,
如果产生的对象同时还会向操作系统发起系统调用,(一个对象同时有用户级和内核级两种资源),那么必须在清除对象的同时回收系统资源
class Foo:
def __init__(self, name, age, f):
self.name = name
self.age = age
self.f = f
def __del__(self):
print('回收资源')
self.f.close()
obj = Foo('cc', 18, open('a.txt', 'r', encoding='utf-8')) # 回收资源(程序运行完毕后自动调用__del__)
print('运行完毕...')
# 结果:
'''
运行完毕...
回收资源
'''
六、反射
反射:是指程序可以访问、检测和修改它本身状态或行为的一种能力
python面对对象中的反射:
通过字符串的形式操作对象相关的属性,python中的一切事物都是对象,都可以使用反射
四个可以实现自省的函数:
注意:
属性的名字必须使用字符串形式(这四个函数都相当于是在操作对象属性字典的key 和value来实现功能的)
6.1 hasattr(object, name)
判断对象是否有某种属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
f1 = Foo('cc', 18)
print(hasattr(f1, 'name')) # True
6.2 getattr(object, name, default = None)
获取对象的属性,如果属性不存在就报错,
可以自定义找不到时返回的值,比如None
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo('cc', 18)
print(getattr(obj, 'name', None)) # cc
6.3 setattr(object, name, value)
设置对象属性,属性存在就修改,没有就添加
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo('cc', 18)
setattr(obj, 'name', 'jason')
setattr(obj, 'sex', 'male')
print(obj.__dict__) # {'name': 'jason', 'age': 18, 'sex': 'male'}
6.4 delattr(object, name)
用于删除对象的属性,属性不存在会报错
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo('cc', 18)
delattr(obj, 'age')
print(obj.__dict__) # {'name': 'cc'}
obj对象的age属性已经被删除