面向对象
什么是面向对象?
面向对象时一种思想,是基于面向过程的。
面向过程:面向过程需要程序员自己处理每一步的操作,就像是炒菜一样,需要准备好各种蔬菜,洗菜,切菜,打开煤气灶,放上锅,倒油。。。等等,直到菜出锅你都要知道,都要自己操作。
面向对象:如果用面向对象来描述炒菜应该是这样的。你要炒菜,但是你不会,你不会不要紧,你有钱是个壕,你找到一个厨师,对他说你要吃满汉全席。厨师走了,忙了一个中午,回来告诉你满汉全席做好了,可以用膳了。
从上面的两种炒菜方式可以看出来面向过程注重的内部细节(炒菜的整个流程),面向对象注重的是结果(菜炒出来了就行,怎么炒的我不关心)。
面向对象时基于面向过程的怎么理解?
还是用上面的炒菜来说明一下,现在我是壕,你是厨师. 因为我是壕, 我可以不会做菜。你是厨师,所以你必须会做菜。那么作为厨师这个对象, 你就需要知道怎么洗菜,切菜,打开煤气。。。。等等。
面向过程和面向对象是密不可分的。
类
光说面向对象,对象是啥?哪里来的?说到这就需要提到另一个概念 类
什么是类?
人以类聚,物以群分。类,类似,相似。程序中的类就是把一些具有相似功能的方法和属性放到一起,组成的一个小的功能集合,就叫做类,类是抽象的。
类的定义
定义格式
class 类名: # class关键字
方法列表
类的构成
类名
属性
方法
class People: # 创建一个类
pass
对象
什么是对象?
面向对象,在程序中都是先有类后有对象的,为什么呢?因为对象是类的一个具体存在。就像你,你是人类,是人类的一个具体的存在,具体的实例,所以一个类的具体的实例又叫做实例对象。同理,对象的方法以及属性,分别叫做实例方法以及实例属性。
创建实例对象
创建对象的过程:
class People: # 首先创建一个类
pass
# 创建类的一个实例,也就是对象,为了方便使用对象,将对象赋值给变量dragon_fang
dragon_fang = People()
对象的实例属性和实例方法
人类有一些特征,比如姓名、年龄、性别等。除了这些特征,人类还有很多行为,比如可以思考、可以奔跑、可以吃饭等。
这些描述性的特征就是一个对象的属性,而行为动作就是对象的方法。
class People:
def cogitate(self):
print("认真思考。。。")
def run(self):
print("可以跑步。。。")
def eat(self):
print("可以吃饭。。。")
dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100
print("name:%s ,age:%d " % (dragon_fang.name, dragon_fang.age))
dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()
通过 对象.属性 的方式可以直接为对象添加一个属性或者使用属性的值,对象.方法()的方式可以直接调用对象的方法。
self 形参,self 是一个形参,代表了调用方法的对象。虽然形参是可以任意命名的,但是为了规
范,这里建议使用self。
self 的使用
既然self 是实例对象的引用,name可不可以在实例方法中通过self 获取实例对象的实例属性?答案是可以的
class People:
def cogitate(self):
print("认真思考。。。")
def run(self):
print("可以跑步。。。")
def eat(self):
print("可以吃饭。。。")
def show(self): # 增加自我介绍方法
print("name:%s ,age:%d " % (self.name, self.age))
dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100
dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()
dragon_fang.show()
# 结果:
# 认真思考。。。
# 可以跑步。。。
# 可以吃饭。。。
# name:DragonFang ,age:100 # show()方法正常执行了
创建多个对象
class People:
def cogitate(self):
print("认真思考。。。")
def run(self):
print("可以跑步。。。")
def eat(self):
print("可以吃饭。。。")
dragon_fang = People()
dragon_fang.name = "DragonFang"
dragon_fang.age = 100
print("name:%s ,age:%d " % (dragon_fang.name, dragon_fang.age))
dragon_fang.cogitate()
dragon_fang.run()
dragon_fang.eat()
xiao_ming = People() # 创建另一个People类的对象,赋值给xiao_ming
# 创建了xiao_ming 打印一下xiao_ming 的属性
print("name:%s ,age:%d " % (xiao_ming.name, xiao_ming.age))
结果信息:
22行报错,People 类没有属性 name 。创建第一个对象的时候添加了属性,dragon_fang 的属性可以正常使用, 创建第二个对象的时候说没有 name 属性,说明了什么? 说明对象的属性是各自独立的,不共享的。
魔法方法
魔法方法 __init__(self)
python官方提供了很多的魔法方法,魔法方法在恰当的时机,会自动执行。__init__(self) 就是其中之一,注意魔法方法两侧各有两条下划线 “_” ,__init__(self) 方法也是一样。(附官方说明:Called after the instance has been created (by new()), but before it is returned to the caller.)
__init__(self) 方法的作用是初始化。通过self引用的实力对象为每一个实例添加属性。因为self 引用了调用方法的实例对象,由此可以得出__init__(self) 方法的执行是在创建对象之后。
class People:
def __init__(self):
self.name = "DragonFang"
self.age = 18
def show(self):
print("name:%s ,age:%d " % (self.name, self.age))
dragon_fang = People()
dragon_fang.show()
xiao_ming = People()
xiao_ming.show()
# 结果为:
# name:DragonFang ,age:18
# name:DragonFang ,age:18
怎么让每个实例对象的名字不相同呢?传参,通过给__init__(self)传参初始化每个实例对象的name、age。
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print("name:%s ,age:%d " % (self.name, self.age))
dragon_fang = People("DragonFang", 19)
dragon_fang.show()
xiao_ming = People("xiaoMing", 20)
xiao_ming.show()
# 结果为:
# name:DragonFang ,age:19
# name:xiaoMing ,age:20
魔法方法__Str__(self)
魔法方法__Str__(self) 的作用是打印对象的描述信息,必须有返回值,且返回值必须是字符串。(附官方说明:Called by str(object) and the built-in functions format() and print() to compute the “informal” or nicely printable string representation of an object. The return value must be a string object.)
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print("name:%s ,age:%d " % (self.name, self.age))
def __str__(self):
return "name:%s ,age:%d " % (self.name, self.age)
dragon_fang = People("DragonFang", 19)
dragon_fang.show()
print(dragon_fang)
# 结果为:
# name:DragonFang ,age:19
# name:DragonFang ,age:19
需要注意 __str__(self) 必须有返回值,而且返回值的类型必须是字符串类型,否则报错。
所以 __str__(self) 的作用一般是用来打印对象的描述信息。
魔法方法__del__(self)
魔法方法__del__(self) 当对象即将被销毁的时候执行。(附官方说明:Called when the instance is about to be destroyed)
什么情况下对象会被销毁?
- 程序结束
- 对象的所有引用被删除
__del__(self) 方法的作用,
- 因为del(self) 方法在对象即将被销毁时调用,所以可以验证对象是否被销毁。
- 因为del(self) 方法在对象即将被销毁时调用,所以也可以做一些其他操作,比如释放资源。
数据的保护
使用对象.属性可以在类的外部修改属性的值,但是这种修改方式不安全。
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "name:%s ,age:%d " % (self.name, self.age)
dragon_fang = People("DragonFang", 19)
dragon_fang.age = -500
print(dragon_fang)
# 结果为:
# name:DragonFang ,age:-500 # 这是传说中的向天再借五百年吗?
怎样确保数据的正确性呢?方法,通过方法设置可以确保数据的正确性。
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "name:%s ,age:%d " % (self.name, self.age)
def set_age(self, new_age):
if new_age >= 0:
self.age = new_age
print("数据不合法")
dragon_fang = People("DragonFang", 19)
dragon_fang.set_age(-500)
print(dragon_fang)
# 结果为:
# 数据不合法
# name:DragonFang ,age:19
你可能会虽然通过方法确保了正确,但是依然可以通过对象.属性的方式设置属性的值,该怎么解决呢?私有,使用私有属性,私有属性配合方法使用能更好的保护数据的正确性。通过在属性前加两条下划线“_”的形式将公有属性变成私有属性
class People:
def __init__(self, name, age):
self.name = name
self.__age = age
def __str__(self):
return "name:%s ,age:%d " % (self.name, self.__age)
def set_age(self, new_age):
if new_age >= 0:
self.__age = new_age
print("数据不合法")
dragon_fang = People("DragonFang", 19)
dragon_fang.set_age(-500)
print(dragon_fang)
dragon_fang.__age
Traceback (most recent call last):
File “E:/workspace/pycharm/pycharm/Demo.py”, line 18, in
dragon_fang.__age
AttributeError: ‘People’ object has no attribute ‘__age’
数据不合法
name:DragonFang ,age:19
报错了,说明在类外不能使用对象.属性名的方式访问私有属性。
不能访问私有属性,能不能访问私有方法?私有方法同样是通过增加两条下划线“_”的形式
class People:
def __init__(self, name, age):
self.name = name
self.__age = age
def __show(self):
print("name:%s ,age:%d " % (self.name, self.__age))
dragon_fang = People("DragonFang", 19)
dragon_fang.__show()
Traceback (most recent call last):
File “E:/workspace/pycharm/pycharm/Demo.py”, line 11, in
dragon_fang.__show()
AttributeError: ‘People’ object has no attribute ‘__show’
报错,说明不能再类外通过对象.方法名() 的方式访问私有方法
伪私有
伪,假的。伪私有,不是真正的私有。python中没有真正意义上的私有都是伪私有。
为什么这么说?
class People:
def __init__(self, name, age):
self.name = name
self.__age = age
def __show(self):
print("name:%s ,age:%d " % (self.name, self.__age))
dragon_fang = People("DragonFang", 19)
dragon_fang._People__show()
# 结果为:
# name:DragonFang ,age:19
私有只是解释器在处理私有属性,私有方法的时候改变了属性 或者方法的名字,从而达到私有的目的。仅供了解,仅供了解,仅供了解。强烈不建议使用,强烈不建议使用,强烈不建议使用。
到此结 DragonFangQy 2018.4.10