面向对象编程
面向对象编程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,张三和李四是两个具体的Student。
所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。
面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。
创建类
类的特殊方法
Python 使用 __ 开头的名字来定义特殊的方法和属性,它们有:
__init__()
__repr__()
__str__()
__call__()
__iter__()
__add__()
__sub__()
__mul__()
__rmul__()
__class__
__name__
构造方法 __init__()
在产生对象之后,我们可以向对象中添加属性。 事实上,还可以通过构造方法,在构造对象的时候直接添加属性:
class Clothes(object):
"""
init_demo
"""
def __init__(self, color="green"):
self.color = color
my_clothes = Clothes()
my_clothes.color
传入有参数的值:
your_clothes = Clothes('orange')
your_clothes.color
表示方法 __repr__() 和 __str__()
:
class Clothes(object):
"""
repr and str demo
"""
def __init__(self, color="green"):
self.color = color
def __str__(self):
"This is a string to print."
return ("a {} clothes".format(self.color))
def __repr__(self):
"This string recreates the object."
return ("{}(color='{}')".format(self.__class__.__name__, self.color))
__str__()
是使用 print 函数显示的结果,类似java中的toString:
my_clothes = Clothes()
print(my_clothes)
__repr__()
返回的是不使用 print 方法的结果:
my_clothes
print(my_clothes.__class__, my_clothes.__class__.__name__, my_clothes.color)
my_clothes.__class__, my_clothes.__class__.__name__, my_clothes.color
类的属性
只读属性:
class Clothes(object):
def __init__(self, price):
self.price = price
# 这样 discount_price 就变成属性了
@property
def discount_price(self):
return self.price * 0.8
这里 discount_price 就是一个只读不写的属性了(注意是属性不是方法), 而price是可读写的属性:
my_clothes = Clothes(100)
print(my_clothes.discount_price) # 80.0
可以修改price属性来改变discount_price:
my_clothes.price = 200
print(my_clothes.discount_price) # 160.0
my_clothes.discount_price()会报错,因为 my_clothes.discount_price 是属性,不是方法;
my_clothes.discount_price=100 也会报错,因为只读。
对于 @property 生成的只读属性,我们可以使用相应的 @attr.setter 修饰符来使得这个属性变成可写的:
class Clothes(object):
def __init__(self, price):
self.price = price
# 这样就变成属性了
@property
def discount_price(self):
return self.price * 0.8
@discount_price.setter
def discount_price(self, new_price):
self.price = new_price * 1.25
测试一下:
my_clothes = Clothes(100)
print(my_clothes.discount_price)
my_clothes.price = 200
print(my_clothes.discount_price)
修改 discount_price 属性:
my_clothes.discount_price = 180
print(my_clothes.price)
print(my_clothes.discount_price)
一个等价的替代如下,用方法:
class Clothes(object):
def __init__(self, price):
self.price = price
def get_discount_price(self):
return self.price * 0.8
def set_discount_price(self, new_price):
self.price = new_price * 1.25
discount_price = property(get_discount_price, set_discount_price)
my_clothes = Clothes(100)
print(my_clothes.discount_price)
my_clothes.price = 200
print(my_clothes.discount_price)
my_clothes.discount_price = 180
print(my_clothes.price)
print(my_clothes.discount_price)
继承
类定义的基本形式:
class ClassName(ParentClass):
"""class docstring"""
def method(self):
return
里面的 ParentClass 就是用来继承的。
class Clothes(object):
def __init__(self, color="green"):
self.color = color
def out_print(self):
return self.__class__.__name__, self.color
my_clothes = Clothes()
my_clothes.color
my_clothes.out_print()
定义一个子类,继承父类的所有方法:
class NikeClothes(Clothes):
def change_color(self):
if self.color == "green":
self.color = "red"
继承父类的所有方法:
your_clothes = NikeClothes()
your_clothes.color
your_clothes.out_print()
但有自己的方法:
your_clothes.change_color()
your_clothes.color
如果想对父类的方法进行修改,只需要在子类中重定义这个类即可:
class AdidasClothes(Clothes):
def change_color(self):
if self.color == "green":
self.color = "black"
def out_print(self):
self.change_color()
return self.__class__.__name__, self.color
him_clothes = AdidasClothes()
print(him_clothes.color)
him_clothes.change_color()
print(him_clothes.color)
print(him_clothes.out_print())
super() 函数
super(CurrentClassName, instance)
返回该类实例对应的父类对象。
刚才 AdidasClothes可以改写为:
class NewAdidasClothes(Clothes):
def change_color(self):
if self.color == "green":
self.color = "black"
def out_print(self):
self.change_color()
print(super(NewAdidasClothes, self).out_print())
her_clothes = NewAdidasClothes()
print(her_clothes.color)
her_clothes.out_print()
new() 方法
new()用来创建一个实例,它至少有一个参数cls,代表当前类。默认情况下__new__()会创建当前类的实例,该方法也可以被重载,重载后也可以创建其他类的实例。
class Fun(object):
def __init__(self, fun):
self.fun = fun
def __new__(cls, *args, **kwargs):
return object.__new__(Fun)
if __name__ == '__main__':
f = Fun.__new__(Fun)
print(type(f))
new()方法只是创建实例,此时拿到的实例并不能正常使用。一个实例需要被__init__()方法初始化后才可以被正常使用。也就是说,正常场景下,我们生成一个类的实例,Python先调用该类的__new()方法创建一个实例,然后再调用__init()方法初始化该实例。__new()__方法存在于object方法中,通常情况下不需要被重载。
可以使用__new__方法创建出其它类的实例。在这种场景下,__new__方法创建后会调用对应类的__init__方法完成初始化:
class Fun(object):
def __init__(self, fun):
self.fun = fun
def __new__(cls, *args, **kwargs):
return Demo(*args, **kwargs)
class Demo(object):
def __init__(self, d):
self.demo = d
if __name__ == '__main__':
f = Fun(1)
print("type f:", type(f))
print("f.demo:", f.demo)
可以看出,f不是Fun类的一个实例 ,而是Demo类的一个实例,拥有Demo类的字段。因为Fun类的__new__方法创建的是一个Demo类实例,而非Fun类本身。因此Fun.__new__方法在return后调用了Demo.__init__方法,以完成该实例的初始化。
接口
接口的调用:
class Clothes(object):
def __init__(self, color="green"):
self.color = color
def out(self):
print("father.")
class NikeClothes(Clothes):
def out(self):
self.color = "brown"
super(NikeClothes, self).out()
class AdidasClothes(object):
def out(self):
print("adidas.")
因为三个类都实现了 out() 方法,因此可以这样使用:
objects = [Clothes(), NikeClothes(), AdidasClothes()]
for obj in objects:
obj.out()