python- 07 再谈抽象(多态、封装和继承)

# 第七章 再谈抽象
# 7.1 对象魔法
# 多态:可对不同类型的对象执行相同的操作,而这些操作就像“被施了魔法”一样能够正常运行
# 封装:对外部隐藏有关对象工作原理的细节
# 继承:可基于通用类创建出专用类
# 7.1.1 多态(无需知道对象所属的类(对象的类型))
# 7.1.2 多态和方法(无需知道对象的构造)
# 7.1.3 封装
'''
o = OpenObject()
o.set_name('Sir Lancelot')
print(o.get_name())
'''
# 7.1.4 继承
# 7.2 类
# 7.2.1 类到底是什么 子类、超类
# 7.2.2 创建自定义类
class Person:
def set_name(self, name):
self.name = name
def get_name(self):
return self.name
def greet(self):
#print('Hello, world! I\'m {}'.format(self.name))
pass
foo = Person()
bar = Person()
foo.set_name('Luke Skywalker')
bar.set_name('Anakin Skywalker')
print(foo.greet())
print(bar.greet())

# 7.2.3 属性函数和方法
class Class:
def method(self):
print('I have a self!')
def function():
print('I dot\'t...')

instance = Class()
print(instance.method())
instance.method = function
print(instance.method())

# 7.2.4 再谈隐藏

# 7.2.4 再谈隐藏(两个_ 禁止访问, 一个_ 不要从外部修改属性或方法)
# 7.2.5 类的命名空间

class MemberCounter:
members = 0
def init(self):
MemberCounter.members += 1

m1 = MemberCounter()
m1.init()
print(MemberCounter.members)

m2 = MemberCounter()
print(MemberCounter.members)
# 7.2.6 指定超类
class Filter:
def init(self):
self.blocked = []
def filter(self, sequence):
return [x for x in sequence if x not in self.blocked]
class SPAMFilter(Filter): # SPAMFilter是Filter的子类
def init(self):
self.blocked = ['SPAM']

f = Filter()
f.init()
print(f.filter([1, 2, 3]))

s = SPAMFilter()
s.init()
print(s.filter(['SPAM', 'SPAM', 'eggs']))

# 7.2.7 深入探讨继承
print(issubclass(SPAMFilter, Filter)) # 判定 SPAMFilter 是不是 Filter的子类
print(issubclass(Filter, SPAMFilter))
print(SPAMFilter.__bases__) # 查看 SPAMFilter 的 基类
print(Filter.__bases__) #

print(isinstance(s, SPAMFilter)) # 判断类 是 对象的实例
print(isinstance(s, Filter))
print(isinstance(s, str))
c = '22'
print(isinstance(c, str))

print(s.__class__) # 查看对象所属于的类
# 7.2.8 多个超类
class Calculator:
def calculate(self, expression):
self.value = eval(expression)

class Talker:
def talk(self):
print('Hi, my valus is {}'.format(self.value))
class TalkingCalculator(Calculator, Talker):
pass

tc = TalkingCalculator()
tc.calculate('1 + 2 * 3')
tc.talk()
print(TalkingCalculator.__bases__)
# 7.2.9 接口和内省
print(hasattr(tc, 'talk')) # 判断tc 中是否存在'talk'方法
print(hasattr(tc, 'fnord'))

print(getattr(tc, 'talk', None))
print(callable(getattr(tc, 'talk', None))) # 用来判定tc 是否可以调用'talk'
print(getattr(tc, 'fnord', None))
print(tc.__dict__) # 查看储存所有值

# 7.2.10 抽象基类
# 7.3 关于面向对象的一些思考

'''
 将相关的东西放在一起。如果一个函数操作一个全局变量,最好将它们作为一个类的属性和方法。
 不要让对象之间过于亲密。方法应只关心其所属实例的属性,对于其他实例的状态,让它们自己去管理就好了。
 慎用继承,尤其是多重继承。继承有时很有用,但在有些情况下可能带来不必要的复杂性。要正确地使用多重继承很难,要排除其中的bug更难。
 保持简单。让方法短小紧凑。一般而言,应确保大多数方法都能在30秒内读完并理解。对于其余的方法,尽可能将其篇幅控制在一页或一屏内。
确定需要哪些类以及这些类应包含哪些方法时,尝试像下面这样做。
(1) 将有关问题的描述(程序需要做什么)记录下来,并给所有的名词、动词和形容词加上标记。
(2) 在名词中找出可能的类。
(3) 在动词中找出可能的方法。
(4) 在形容词中找出可能的属性。
(5) 将找出的方法和属性分配给各个类。
有了面向对象模型的草图后,还需考虑类和对象之间的关系(如继承或协作)以及它们的职责。为进一步改进模型,可像下面这样做。
(1) 记录(或设想)一系列用例,即使用程序的场景,并尽力确保这些用例涵盖了所有的功能。
(2) 透彻而仔细地考虑每个场景,确保模型包含了所需的一切。如果有遗漏,就加上;如果有不太对的地方,就修改。不断地重复这个过程,直到对模型满意为止。
有了你认为行之有效的模型后,就可以着手编写程序了。你很可能需要修改模型或程序的某些部分,所幸这在Python中很容易,请不用担心。只管按这里说的去做就好。
(如果你需要更详细的面向对象编程指南,请参阅第19章的推荐书目。)
'''
# 7.4 总结
'''
 对象:对象由属性和方法组成。属性不过是属于对象的变量,而方法是存储在属性中的函数。相比于其他函数,
(关联的)方法有一个不同之处,那就是它总是将其所属的对象作为第一个参数,而这个参数通常被命名为self。
 类:类表示一组(或一类)对象,而每个对象都属于特定的类。类的主要任务是定义其实例将包含的方法。
 多态:多态指的是能够同样地对待不同类型和类的对象,即无需知道对象属于哪个类就可调用其方法。
 封装:对象可能隐藏(封装)其内部状态。在有些语言中,这意味着对象的状态(属性)只能通过其方法来访问。
在Python中,所有的属性都是公有的,但直接访问对象的状态时程序员应谨慎行事,因为这可能在不经意间导致状态不一致。
 继承:一个类可以是一个或多个类的子类,在这种情况下,子类将继承超类的所有方法。
你可指定多个超类,通过这样做可组合正交(独立且不相关)的功能。为此,一种常见的做法是使用一个核心超类以及一个或多个混合超类。
 接口和内省:一般而言,你无需过于深入地研究对象,而只依赖于多态来调用所需的方法。然而,如果要确定对象包含哪些方法或属性,有一些函数可供你用来完成这种工作。
 抽象基类:使用模块abc可创建抽象基类。抽象基类用于指定子类必须提供哪些功能,却不实现这些功能。
 面向对象设计:关于该如何进行面向对象设计以及是否该采用面向对象设计,有很多不同的观点。无论你持什么样的观点,都必须深入理解问题,进而创建出易于理解的设计。

callable(object) 判断对象是否是可调用的(如是否是函数或方法)
getattr(object,name[,default]) 获取属性的值,还可提供默认值
hasattr(object, name) 确定对象是否有指定的属性
isinstance(object, class) 确定对象是否是指定类的实例
issubclass(A, B) 确定A是否是B的子类
random.choice(sequence) 从一个非空序列中随机地选择一个元素
setattr(object, name, value) 将对象的指定属性设置为指定的值
type(object) 返回对象的类型
'''
'''
a = int(input('请输入一个整数:'))
#print(x in range[a] if y in range[x] and (y ** 2 < x) and (y % x = 0))
b = []
c = []
for x in range(2, a + 1):
d = 0
for y in range(2, x):
if (y ** 2 <= x) and (x % y == 0):
d = 1
break
if d == 1:
b.append(x)
else:
c.append(x)
print(b)
print(c)
'''

猜你喜欢

转载自www.cnblogs.com/fuyouqiang/p/11844639.html