Day04 面向对象编程基础
学习目标
- 描述对象和类
- 定义带数据域和方法的类
- 使用构造方法调用初始化来创建和初始化数据域以构建一个对象
- 使用self参数引用对象本身
面向对象思想有三大要素:封装、继承和多态
为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。
类和对象
类和对象
简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。
为对象定义类
关键点:类定义对象的特征和行为
- 一个对象的特性就像人的身份证号码,Python会在运行时自动对每一个对象赋予一个独特的id来辨识这个对象
- 一个对象的特征和属性是用变量表示的,被称之为数据域
- 方法也被称为函数,通过调用对象上的方法可以让对象完成某个动作,python使用方法来定义一个对象的行为
- 对象就是累的一个实例
定义类
在Python中可以使用class关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来
以上实例定义了一个类,类名通常实在关键词class后,其后紧随一个冒号(:),初始化程序总是被命名为 _ _ init _ _,这个方法被称为初始化程序,它是在创建和初始化这个新对象时被调用的。
下面示例一个小程序
#打印进度条
import time
class Zcz(object):
def __init__(self):
self.count = 1
def jindutiao(self):
for i in range(0,100):
time.sleep(0.1)
if i % 5 == 0:
res = '#'*self.count
print('%s %d%%'%(res,(i+5)))
self.count += 1
if __name__ == '__main__':
zcz = Zcz()
zcz.jindutiao()
构造对象完成两个任务:
- 在内存中为类创建一个对象
- 调用类的 _ _ init _ _方法来初始化对象
构造方法的语法规则是:类名(参数)
访问可见性问题
对象成员是指它的数据域和方法。数据域也被称为实例变量,因为每个对象(实例)的数据域都有一个特定值。方法也被称为实例变量,因为方法被一个对象(实例)调用来完成对象上的动作
私有变量,变量名前面加"_ _"
如果非要使用私有变量,那么可以使用dir(class())去查看它真正的名字.
私有变量/函数,在类内部可以直接调用.
如果你想体现一个变量/函数特别重要你可以使用"_"
class Test:
def __init__(self, foo):
self.__foo = foo
def __bar(self):
print(self.__foo)
print('__bar')
def main():
test = Test('hello')
# AttributeError: 'Test' object has no attribute '__bar'
test.__bar()
# AttributeError: 'Test' object has no attribute '__foo'
print(test.__foo)
if __name__ == "__main__":
main()
Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来“妨碍”对它们的访问
不变对象和可变对象
当将一个可变对象传给函数时,函数可能会改变这个对象的内容
python中的数字和字符串都是不可变的对象。他们的内容不能被改变。当将一个不可变对象传给函数时,对象不会被改变。但是,如果你给函数传递一个可变对象,那么对象的内容就可能有变化。以下示例演示不可变对象和不可变对象参数在函数中的不同
当你将一个对象传递给函数,就是将这个对象的引用传递给函数。但是传递不可变对象和可变对象之间还有更重要的区别。
- 像数字或者字符串这样的不可变对象参数,函数外的对象的原始值并没有被改变
- 如果是可变对象参数,如果对象的内容在函数内被改变,则对象的原始值被改变
隐藏数据域
作用就是使数据域私有来保护数据,让类更易于维护
私有数据域和方法可以在类内部被访问,但它们不能再类外被访问。为了让客户端访问数据域,就要提供一个get方法返回它的值。为了使数据域可以被更改,就要提供一个set方法去设置一个新值。
通俗来讲,get方法就是指获取器(或访问器),set方法就是指设置器(或修改器)
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
# 访问器 - getter方法
@property
def name(self):
return self._name
# 访问器 - getter方法
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('王大锤', 12)
person.play()
person.age = 22
person.play()
# person.name = '白元芳' # AttributeError: can't set attribute
if __name__ == '__main__':
main()
继承
子类构造函数基础父类构造函数过程如下:
实例化对象c ----> c 调用子类__init__() ---- > 子类__init__()继承父类__init__() ----- > 调用父类 init()
你现在偷的懒都是以后给自己挖的坑!既来之则安之!加油照哥