目录
1 概述
面向对象中的对象是指人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。
面向对象是指一件事“该让谁来做”,然后那个“谁”就是对象,他要怎么做是他自己的事,多个问题的参与者-对象合力能把问题解决。
面向过程其实是最为实际的一种思考方式,就算是面向对象的方法也是含有面向过程的思想。可以说面向过程是一种基础的方法。
2 类和对象
类就是模具,定义了对象应该是什么样的,对象是由模具创建出来的,和模具样式一样。
类由属性(变量)和行为(函数)组成。
2.1 类定义和对象创建
类的语法格式:
class 类名(object):
方法列表
2.2 __init__方法
在类中增加一个特殊的方法,__init__方法(该方法在创建对象时自动调用),在该方法中使用self设置属性即可,以后一旦创建对象,不需要额外设置属性。
由于__init__方法在创建时刻自动调用,我们可在创建时将我们指定的参数值传递给对象来实现设置对象初始属性值的目的。
__init__函数注意点:
- __init__()方法,在创建一个对象时默认被调用,不需要手动调用;
- __init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y);
- __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去。
2.3 self参数
对象的属性是独有的,函数代码是共享的。函数共享,就会出现一个问题,当通过对象去调用函数的时候,函数如何区分是那个对象调用它?答案就是self参数。
类内的实例方法第一参数都必须是self,而且self参数是由python自动传递的,不需要手动传递。
self的作用就是用来区分函数是由那个对象调用。
2.4 保护对象数据
- 变量名加俩下划线,变量为私有变量,只能在类内访问,类外不可访问。例如:__name.
- 变量名加一个下划线,变量为保护变量,不建议类外访问,但类外可访问.例如:_name.
- 变量名不加任何下划线修饰,变量为公有变量,类内类外都可以访问。例如:name
3 继承
3.1 概述
继承是面向对象的重要特征之一。继承实现了代码的重用。重用已经存在的数据和行为,减少代码的重新编写。从子类角度来讲,子类可以扩展父类的行为,扩展父类的功能。
3.2 语法
# 父类
class Father(object):
def __init__(self):
self.money = 100000
self.qq = "666"
def make_pie(self):
print("祖传传统工艺煎饼果子...")
# 子承父业
class Son(Father):
pass
# 创建儿子对象
son = Son()
# 展示儿子财富和技能
print("儿子的钱数:%d" % son.money)
print("儿子的QQ:%s" % son.qq)
son.make_pie()
3.3 私有属性和方法特点
- 私有的属性,不能通过对象直接访问,但是可以通过方法访问;
- 私有的方法,不能通过对象直接访问;
- 私有的属性、方法,不会被子类继承,也不能被访问;
- 一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用。
4 类属性和类方法
4.1 实例属性和实例方法
class NewsPaper(object):
# 实例方法
def __init__(self, title, content):
self.title = title # 实例属性
self.content = content # 实例属性
# 实例方法
def show_news(self):
print("报纸标题:%s" % self.title)
print("报纸内容:%s" % self.content)
# 创建报纸
news1 = NewsPaper("传智周刊", "人生苦短,我用python!")
news2 = NewsPaper("传智特刊", "C++从入门到颈椎康复指南!")
# 显示报纸内容
news1.show_news()
news2.show_news()
# 当我修改了news1的title
news1.title = "传智月刊"
# 再次显示报纸内容
print("---------------")
news1.show_news()
news2.show_news()
# 我们发现,news2实例对象的标题并没有发生改变
实例方法和实例属性是实例对象特有,并不共享。
4.2 类属性和类方法
如果我们想统计报纸发行了多少份,也就是报纸实例对象创建了多少个,怎么做?除了全局变量,我们也可设置类属性。
class NewsPaper(object):
# 类属性
print_times = 0
# 实例方法
def __init__(self, title, content):
self.title = title # 实例属性
self.content = content # 实例属性
# 累加类属性变量
NewsPaper.print_times += 1
# 实例方法
def show_news(self):
print("报纸标题:%s" % self.title)
print("报纸内容:%s" % self.content)
# 创建报纸
news1 = NewsPaper("传智周刊", "人生苦短,我用python!")
news2 = NewsPaper("传智特刊", "C++从入门到颈椎康复指南!")
# 显式报纸发行次数(访问类属性)
print(news1.print_times)
print(news2.print_times)
print(NewsPaper.print_times)
# 修改类属性
news1.print_times = 100 # 错误方式,python会认为是给对象动态添加属性
NewsPaper.print_times = 100 # 正确修改类属性方式
类属性也属于所有实例对象共享的关键数据,正如上例,我们并不希望外界直接操作类属性,解决此问题,可以给类属性增加访问控制权限,可将类属性设置为私有属性,通过类方法给外界提供访问接口。
class NewsPaper(object):
# 类属性
__print_times = 0
# 实例方法
def __init__(self, title, content):
self.title = title # 实例属性
self.content = content # 实例属性
# 累加类属性变量
NewsPaper.__print_times += 1
# 实例方法
def show_news(self):
print("报纸标题:%s" % self.title)
print("报纸内容:%s" % self.content)
# 类方法(封装类属性,外界提供访问接口,保护类属性)
@classmethod
def get_times(cls):
return cls.__print_times
# 创建报纸
news1 = NewsPaper("传智周刊", "人生苦短,我用python!")
news2 = NewsPaper("传智特刊", "C++从入门到颈椎康复指南!")
# 显式报纸发行次数(访问类属性)
print(news1.get_times())
print(news2.get_times())
print(NewsPaper.get_times())
总结:类属性和类方法归所有本类型的实例对象共享,可通过实例对象访问,也可通过类对象访问。
4.3 静态方法
class NewsPaper(object):
# 类属性
__print_times = 0
# 实例方法
def __init__(self, title, content):
self.title = title # 实例属性
self.content = content # 实例属性
# 累加类属性变量
NewsPaper.__print_times += 1
# 实例方法
def show_news(self):
print("报纸标题:%s" % self.title)
print("报纸内容:%s" % self.content)
# 类方法(封装类属性,外界提供访问接口,保护类属性)
@classmethod
def get_times(cls):
return cls.__print_times
# 静态方法
@staticmethod
def static_method():
# 静态方法(可通过类名访问类属性)
# 静态方法不可访问实例属性
print(NewsPaper.__print_times)
print("我是静态方法!")
# 创建报纸
news1 = NewsPaper("传智周刊", "人生苦短,我用python!")
news2 = NewsPaper("传智特刊", "C++从入门到颈椎康复指南!")
# 通过实例对象访问静态方法
news1.static_method()
# 通过类对象访问静态方法
NewsPaper.static_method()
静态方法没有默认的self或者cls参数,如果方法并没有访问实例属性或者类属性,我们可将其设置为静态方法,减少了参数的传递。
静态方法可通过类对象或者实例对象访问,静态方法内部不可访问实例属性,但可通过类名访问类属性。
4.4 __new__方法
__new__方法只能用于从object继承的新式类。__new__方法负责创建实例对象,也可理解__new__方法为创建实例对象的一个工厂。
一个实例对象的创建过程是:
1)类对象调用__new__方法创建一个实例对象
2)实例对象再调用__init__函数完成初始化
其中,__new__方法和__init__方法在创建对象的时候被自动调用。
__new__方法不是必须定义的,如果没有定义会默认调用object.__new__去创建一个对象,如果定义了就重写了__new__方法,可以自定义创建对象的行为
class Car(object):
def __new__(cls, *args, **kwargs):
print("__new__方法被自动调用!")
return super().__new__(cls)
def __init__(self, name):
print("__init__方法被自动调用!")
self.color = "紫色"
self.name = name
# 创建汽车
car = Car("凯迪拉克")
# 参数"凯迪拉克"先传递给__new__方法
# __new__方法再将参数"凯迪拉克"传递给__init__方法
4.5 __del__方法
class Person(object):
def __init__(self):
print("__init__函数调用!")
def __del__(self):
print("__del__函数调用!")
# 创建对象
person = Person()
# 销毁对象
del person