Python学习笔记09_面向对象编程Object Oriented Programming
来源:互联网 发布:淘宝原创品牌 知乎 编辑:程序博客网 时间:2024/06/06 05:42
面向对象编程
- 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。
面向对象的程序设计把计算机程序视为一组对象的集合,每个对象可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
# 面向过程<<< std1 = {'name': 'Michael', 'score': 98}<<< std2 = {'name': 'Bob', 'score': 81}<<< def print_score(std): print('%s: %s' % (std['name'], std['score']))
# 面向对象class Student(object): def __init__(self, name, score): self.name = name self.score = score def print_socre(self): print('%s %s' % (self.name, self.score))<<< bart = Student('Bart Simpson', 59)<<< lisa = Student('Lisa Simpson', 87)<<< bart.print_score()<<< bart.print_score()
类和实例
- 和普通的函数相比,在类中定义的函数第一个参数永远是实例变量self,并且在调用时不用传递该参数。
- 数据封装,方法是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据,通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
访问限制
如果要让类的内部属性不被外部访问,可以把属性的名称前加上两个下划线
__
。不能直接访问__name
是因为Python解释器对外把__name
变量改成了_Student__name
,所以仍然可以通过_Student__name
来访问__name
变量。class Student(object): def __init__(self, name, score): self.__name = name self.__score = score def print_socre(self): print('%s %s' % (self.__name, self.__score)) def get_name(self): return self.__name def get_score(self): return self.__score def set_score(self, score): if 0 <= score <= 100: self.__score = score else: raise ValueError('bad score')
- 类似
__xxx__
的,是特殊变量,是可以直接访问的。 - 类似
_xxx
的,单下划线开头的实例变量名,外部是可以直接访问的,约定俗成’虽然我可以被访问,但是,请把我视为私有变量,不要随意访问’。
继承和多态
- 开闭原则,对扩展开放,允许新增Animal子类;对修改封闭,不需要修改依赖Animal类型的run_twice()函数。
- 动态语言的”鸭子类型”,它并不要求严格的继承体系,一个对象只要”看起来像鸭子,走起路来像鸭子”,那么它就可以被看做是鸭子。Python的”file-like object”就是一种鸭子类型,对真正的文件对象,它有一个read()方法,返回其内容,但是,许多对象,只要有read()方法,都被视为”file-like object”。许多函数接收的参数就是”file-like object”,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。
获取对象信息
- 判断对象类型,使用
type()
函数,可判断基本类型、函数、类,type()函数返回对应的Class类型。 判断一个对象是否是函数。
<<< import types<<< def fn(): pass<<< type(fn) == types.FunctionTypeTrue<<< type(abs) == types.BuiltinFunctionTypeTrue<<< type(lambda x: x) == types.LambdaTypeTrue<<< type((x fir x in range(10))) == types.GeneratorType
判断class的类型,可以使用
isinstance()
函数。# 继承关系是 object -> Animal -> Dog -> Husky<<< a = Animal()<<< d = Dog()<<< h = Husky()<<< isinstance(h, Husky)<<< isinstance(h, Dog)<<< isinstance(h, Animal)True<<< isinstance(d, Husky)False
<<< isinstance([1, 2, 3], (list, tuple))True
dir()
函数,获得一个对象的所有属性和方法,它返回一个包含字符串的list。getattr()
、setattr()
、hasattr()
,直接操作一个对象的状态。
实例属性和类属性
- 在编写程序的时候,不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
del s.name # 删除实例的name属性
使用slots
给实例绑定属性和方法,给类绑定实例和方法。
class Student(object): pass
<<< s = Student()<<< s.name = 'Michael' # 动态给实例绑定一个属性<<< print(s.name)Michael
# 给实例绑定一个方法<<< def set_age(self, age): # 定义一个函数作为实例方法 self.age = age<<< from types import MethodType<<< s.set_age = MethodType(set_age, s) # 给实例绑定一个方法<<< s.set_age(25)25
<<< s2 = Student() # 创建新的实例<<< s2.age(25) # 尝试调用方法AttributeError:……
# 给class绑定方法<<< def set_score(self, score) self.score = score<<< Student.set_score = set_score<<< s.set_score(100)<<< s.score100<<< s2.set_score(99)<<< s2.score99
使用
__slots__
限制实例的属性,__slots__
定义的属性仅对当前类起作用,对继承的子类不起作用。除非在子类中也定义__slots__
,这样,子类允许定义的属性就是自身的__slots__
加上父类的__slots__
。class Student(object): __slots__ = ('name', 'age')
<<< s = Student() # 创建新的实例<<< s.name = 'Michael' # 绑定属性'name'<<< s.age = 25 # 绑定属性'age'<<< s.score = 99 # 绑定属性'score'AttributeError:……
使用@property
@property,只定义getter方法,不定义setter方法就是一个只读属性。
@propertydef score(self): return self._score@score.setterdef score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0~100!') self._score = value@propertydef birth(self): return self._birth@birth.setterdef birth(self, value): self._birth = value@propertydef age(self): return 2015 - self._birth
<<< s = Student()<<< s.score = 60 # OK, 实际转化为s.set_score(60)<<< s.score # OK, 实际转化为s.get_score
多重继承
- MinIn
class Dog(Mammal, RunnableMixIn, CarnivorousMixIn)
定制类
__str__
,__str__
返回用户看到的字符串,__repr__
返回程序开发者看到的字符串。
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object(name = %s)' % self.name
__repr__ = __srt____iter__
,使一个类可以被作用于for ... in
循环返回一个迭代对象,Python的for循环会不断调用该迭代对象的__next__
方法拿到循环的下一个值。class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器 def __iter__(self): return self # 实例本身就是迭代对象,故返回自己 def __next__(self): self.a self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000 # 退出循环的条件 raise StopIteration() return self.a # 返回下一个值
for n in Fib(): print(n)
__getitem
,使一个类可以像list那样按照下标取出元素。__setitem
、__delitem__
。class Fib(object): def __getitem__(self, n): a, b = 1, 1 for x in range(n): a, b = b, a+b return a
<<< f = Fib()<<< f[0]1
# 切片class Fib(object): def __getitem__(self, n): if isinstance(n, int): # n是索引 a, b =1, 1 for x in range(n): a, b = b, a+b return a if isinstance(n, slice): # n是切片 start = n.start stop = n.stop if start is None: start = 0 a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a+b return L
<<< f = Fib()<<< f[0:5][1, 1, 2, 3, 5]
__getattr__
,动态获取属性和方法。在没有找到属性的情况下,才调用__getattr__
。任意调用s.abc都会返回None,因为我们定义的__getattr__
默认返回就是None。要让class只响应特定的几个属性,我们要按照约定,抛出AttributeError
的错误。class Student(object): def __init__(self): self.name = 'Michael' def __getattr(self, attr): if attr == 'score': return 99 if attr == 'age': return lambda: 25 raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
<<< s = Student()<<< s.name'Michael'<<< s.score99<<< s.age()25
__call__
,实现调用实例方法直接在实例本身上调用。_call_
也可以定义参数,对实例调用好比对一个函数调用,可以把对象看成函数,把函数看成对象。因为类的实例是运行期创建出来的,如果你把对象看成函数,那么函数本身也可以在运行期动态创建出来。判断一个对象是否能被调用,能被调用的对象就是一个callable
对象。class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name)
<<< s = Student('Michael')<<< s()My name is Michael.
<<< callable(Student())True<<< callabke(max)True<<< callable([1, 2, 3])False<<< callable(None)False<<< callable('str')False
枚举类
Enum
<<< from enum import Enum<<< Week = Enum('Week',('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'))<<< from name, member in Week.__members__.items(): print(name, '=>', member, ',', member.value)
from enum import Enum, unique@unique # @unique装饰器帮助检查没有重复值class Weekday(Enum): Sun = 0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6
<<< day1 = Weekday<<< print(day1)Weekday.Monday<<< print(Weekday.Tue)Weekday.Tue<<< print(Weekday['Tue'])Weekday.Tue<<< print(Weekday.Tue.value)2<<< print(day1 == Weekday.Mon)True<<< print(day1 == Weekday.Tue)False<<< print(Weekday(1))Weekday.Mon<<< print(day1 == Weekday(1))True<<< Weekday(7)ValueError<<< for name, member inWeekday.__members__.items(): print(name, '=>' member)Sun => Weekday.SunMon => Weekday.MonTue => Weekday.TueWed => Weekday.WedThu => Weekday.ThuFri => Weekday.FriSat => Weekday.Sat
元类
type()
# hello.pyclass Hello(object): def hello(self, name='world'): print('Hello, %s.' % name)
<<< form helllo import Hello<<< h = Hello()<<< h.hello()Hello, world.<<< print(type(Hello))<class 'type'><<< print(type(h))<class 'hello.Hello'>
# type()函数创建新的类型<<< def fn(self, name='world'): print('Hello, %s.' % name)
- Python学习笔记09_面向对象编程Object Oriented Programming
- Python Object Oriented Programming (面向对象编程) Generator
- Object Oriented Programming面向对象编程
- 面向对象编程OOP(Object Oriented Programming)
- 面向对象编程Object Oriented Programming
- 面向对象编程(Object-Oriented Programming)
- 面向对象编程(Object-oriented programming,OOP)
- 面向对象编程(OOP)Object Oriented Programming
- C#面向对象编程(Object-Oriented Programming)
- OOP(Object Oriented Programming 面向对象程序设计)
- 面向对象程序设计(OOP-Object Oriented Programming)
- C#面向对象(Object-Oriented Programming)
- (OOP:Object Oriented Programming)面向对象
- 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)
- Javascript高级程序设计第二版第六章--面向对象程序设计(Object-Oriented Programming)简称OOP编程--笔记
- 《JAVA编程思想》学习笔记一:面向对象思想(Object-oriented)
- 【Java】Java学习笔记之一 ----面向对象(Object-Oriented)
- 面向对象编程(Object Oriented Programming)概念总结及延伸(一)
- centos下面flash_player_npapi_linux.i386.tar.gz如何安装
- T-SQL 语句(二)—— 数据表操作
- 杀毒 OR 病毒
- 基础练习 数列特征
- Windows下配置Chrome WebDriver
- Python学习笔记09_面向对象编程Object Oriented Programming
- Java中String的不变性理解
- 间隔年(退休)的日常安排——北漂18年(82)
- 最少拦截系统
- 李开复:如何设计你的年度计划
- TextView文本超出截断(显示...)
- 烦人的幻灯片(拓扑 很烦人)
- [leetCode刷题笔记]2017.02.09
- 面向对象-接口