Python — 面向对象编程基础
活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,
我们先来看看比较正式的说法。
把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。
类和对象
对象是具体的东西。在面向对象编程的世界中,一切
皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们
把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一
个叫做“类”的东西
""" 标识 函数名字 (): 有冒号就要缩进一个tab 在Python中所有的函数都有返回值,如果你没有给予return则默认返回出None,如果你给予了,则返回你给予的值 """" def funcName(): ..... return .... """ 标识 类名 () : 有冒号就要缩进一个tab """ class className(object): ........
""" 1.导入库, import 库名 2. for 循环,如果计数的情况则使用 开始 结束 不长 range的区间是一个前闭后开. range(start,end,[step]) 3. 格式化输出 3.1 %-->%(),%d后接整型,%f后接浮点,%s后接字符串. 3.2 {}-->format(),它可以直接传入任何类型,然后格式化输出. 4.print 控制台(terminal)打印 4.1 end 以什么方式结尾,默认以换行符"\n" 4.2 flush 刷新缓冲区. """
""" 类中的函数可以有自己的参数 当你想共享这个参数的时候,那么就打上"self"的印记. """ class A(object): def __init__(self,a): self.a = a def B(self,b): self.b = b print(b) def C(self): print(self.b) J = A(1000) J.B(10) J.C()
# object 不是一个参数 """ 定义类只有两步: 1. 使用标识符class ClassName(object): 2. 重写__init__函数,但是需要记住,一定要打上一个"self"的标记 因为后面会学到继承,当在继承的时候可能就会有函数名相撞的情况. 或者说,类中会含有多个变量,多个函数,那么就需要使用"self"手段去区分. 3. 类的传参是在__init__函数中的.需要注意的是,如果你的参数可能被多个函数都使用,那么 你才在__init__函数中去定义参数 """ class Student(object): def __init__(self,name): # 多个打印用","进行分隔. print(name) Student(10
# 在Python2中这个object一定要写,但是在Python3中可写可不写(默认就继承了object). # class Student(object): # __init__是一个特殊方法用于在创建对象时进行初始化操作 # 通过这个方法我们可以为学生对象绑定name和age两个属性 def __init__(self, name, age): self.name = name self.age = age def study(self, course_name): print('%s正在学习%s.' % (self.name, course_name)) # PEP 8要求标识符的名字用全小写多个单词用下划线连接 # 但是很多程序员和公司更倾向于使用驼峰命名法(驼峰标识) def watch_av(self): if self.age < 18: print('%s只能观看《熊出没》.' % self.name) else: print('%s正在观看岛国爱情动作片.' % self.name # 实例 student = Student()
# 学类会有些累. class Student(object): """ 第二步初始化,初始化自己. 当你的类有一些公用变量的时候,你就可以初始化 初始化中经常放入公有的变量. """ def __init__(self,name): """ 在类中,一切的变量和函数都要印记(self) """ self.name = name def def1(self,num): self.num = num print(self.num) print(self.name) def def2(self): print(self.num) print(self.name) if __name__ == "__main__": # 实例,类名带括号“Student()”,直接运行初始化函数 student = Student('杜苗苗') student.def1(100) student.def2()
def main(): # 创建学生对象并指定姓名和年龄 stu1 = Student('骆昊', 38) # 给对象发study消息 stu1.study('Python程序设计') # 给对象发watch_av消息 stu1.watch_av() stu2 = Student('王大锤', 15) stu2.study('思想品德') stu2.watch_av() if __name__ == '__main__': main()
对于上面的代码,有C++、Java、C#等编程经验的程序员可能会问,我们给Student
对象绑定的name
和age
属性到底具有怎样的 访问权限(也称为可见性)。因为在很多面向对象编程语言中,我们通常会将对象的
属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通
常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限
只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,
下面的代码可以验证这一点。
# 私有变量,变量名前面加"__" # 如果非要使用私有变量,那么可以使用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并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个
名字来“妨碍”对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可
以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。
因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。
class Test: def __init__(self, foo): self.__foo = foo def __bar(self): print(self.__foo) print('__bar') def main(): test = Test('hello') test._Test__bar() print(test._Test__foo) if __name__ == "__main__": main()
面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里
我们先说一下什么是封装。我自己对封装的理解是“隐藏一切可以隐藏的实现细节,只向外界暴露
(提供)简单的编程接口”。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在
我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是
说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细
节(方法的内部视图)。
练习1:定义一个类描述数字时钟
class Clock(object): """数字时钟""" def __init__(self, hour=0, minute=0, second=0): """初始化方法 :param hour: 时 :param minute: 分 :param second: 秒 """ self._hour = hour self._minute = minute self._second = second def run(self): """走字""" self._second += 1 if self._second == 60: self._second = 0 self._minute += 1 if self._minute == 60: self._minute = 0 self._hour += 1 if self._hour == 24: self._hour = 0 def __str__(self): """显示时间""" return '%02d:%02d:%02d' % \ (self._hour, self._minute, self._second) def main(): clock = Clock(23, 59, 58) while True: print(clock) sleep(1) clock.run() if __name__ == '__main__': main()
from math import sqrt class Point(object): def __init__(self, x=0, y=0): """初始化方法 :param x: 横坐标 :param y: 纵坐标 """ self.x = x self.y = y def move_to(self, x, y): """移动到指定位置 :param x: 新的横坐标 "param y: 新的纵坐标 """ self.x = x self.y = y def move_by(self, dx, dy): """移动指定的增量 :param dx: 横坐标的增量 "param dy: 纵坐标的增量 """ self.x += dx self.y += dy def distance_to(self, other): """计算与另一个点的距离 :param other: 另一个点 """ dx = self.x - other.x dy = self.y - other.y return sqrt(dx ** 2 + dy ** 2) def __str__(self): return '(%s, %s)' % (str(self.x), str(self.y)) def main(): p1 = Point(3, 5) p2 = Point() print(p1) print(p2) p2.move_by(-1, 2) print(p2) print(p1.distance_to(p2)) if __name__ == '__main__': main()
# 输入两个数字,打印这两个数的 # 差,和、乘、除、整除、取余、平方 class YUantingting(object): def __init__(self,a,b): print(a+b,a-b,a*b) YUantingting(1,2)
""" if 条件: 执行体 elif 条件: 执行体 else: 如果if不走.则走else """ # object 不是一个参数 # class # 输入一个年龄,如果年龄大于18小于20可观看4级 # 如果年龄大于20小于50-->岛国 # 如果大于50岁,别看啦,扛不住的》 class Joker(object): def __init__(self,age): if 18<= age <=20: print('4级') elif 20< age <= 50: print('岛国') else: print('扛不住') Joker(18)
""" 定义3个函数,第一个函数:年龄判断 <18 ,18<40,40> 第二个函数:性别判断: 男,女,未知 第三个函数:打印 (年轻,中年,老年)和性别 """ class Name(object): def __init__(self,age,gener): self.age = age self.gener = gener def Age(self): if self.age <= 18: print('年轻') elif 18< self.age <= 40: print('中年') else: print('老年') def Gener(self): if self.gener == '男': print('您 ! 是! 男~') elif self.gener == "女": print('您 ! 是! 女~') else: print('您好~') Joker = Name(18,'男') Joker.Age() Joker.Gener()
# 1.判断一个数字是不是素数. # 2.数字时钟..(写闹钟,可以设定一个时间,打印闹钟响了) """ for xxx: .... else: .... 当for循环能够顺利执行完毕,也就是说没有brek,则走else 否则else不走 for i in range(10): print(i) else: print('hahah') """ class Name(object): """ 判断一个数字是否是素数 """ def __init__(self,num): """ Argus: ----- num: int类型的数字 """ self.num = num def Check(self): """ 检查self.num是不是素数 """ for i in range(2,self.num): if self.num % i == 0: print('不是素数') break else: print('是素数') name = Name(11) name.Check()