# coding = utf-8
#######################################################################
# 1. 对象
# 创建对象
o1 = object()
# 1.1 多态
# 无须知道对象属于哪种对象,也能对其执行操作,且操作的行为将随对象所属的类型而异
# Python内置的+ count函数都是多态的
# 对于字符串 数 序列 不需要知道它属于哪个对象,都可以执行+方法 这就是多态
print('string1' + 'string2')
print(1+2)
print([1, 2, 3]+[4, 5])
print()
print('abc'.count('a'))
print(['a', 'b', 1, 2, 'a', 3, 'a', 'a'].count('a'))
print()
# 自定义函数 使其支持多态
def addfunc(x, y):
return x + y
print(addfunc('ABC','Tana'))
print(addfunc(1, 3))
print(addfunc([1, 3], [5, 4, 5]))
print()
#######################################################################
# 1.2 封装
# 封装是指向外部隐藏不必要的细节
#######################################################################
# 1.3 继承
# 继承是指某个对象继承于另个一个对象,是其不用实现另一个对象的方法,就可以使用另一个对象的方法
# 子类扩展超类的定义
#######################################################################
# 2 类
# 2.1 类
# 每个对象都属于特定的类,并成为该类的实例
# 一个类的对象是另一个类的对象的子集时,前者就是后者的子类,后者是前者的超类(基类)
#######################################################################
# 2.2 自定义类
# class语句创建独立的命名空间,用于在自重定义函数
class person:
def set_name(self, name):
self.name = name
def get_name(self, name):
return self.name
def greet(self):
print('Hello,{}'.format(self.name))
aperson = person()
bperson = person()
aperson.set_name('Tana')
bperson.set_name('Joe')
aperson.greet()
bperson.greet()
print()
#######################################################################
#2.3 属性 函数 方法
# 方法 与对象属性相关联的函数称为方法
# 方法与函数的区别在于参数self上,方法将其第一个参数关联到它所属的实例上,因此无需提供这个参数
class AClass:
def method(self):
print('I have a self')
def function():
print("I don't ...")
instance = AClass() #创建对象一定要有()
instance.method()
instance.method = function
instance.method()
print()
class Bird:
song = 'Squaak'
def sing(self):
print(self.song)
bird = Bird()
bird.sing()
print()
birdsong = bird.sing
birdsong()
print()
# 变量birdsong 指向的是关联的方法bird.sing
#######################################################################
# 2.4 再谈隐藏
# 可以通过在方法或属性名称前以两个下划线打头,来使方法或属性称为私有的
class Secretive:
def __inaccessible(self):
print("Bet you can't see me ...")
def accessible(self):
print('The secret message is :')
s = Secretive()
s.accessible()
# 在类的定义中,对所有的以两个下划线打头的名称都进行转换,即在开头加上一个下划线和类名
s._Secretive__inaccessible()
# 在Python中无法禁止别人访问对象的私有方法和属性,
# 但可以通过在名称前加一个下划线加以标识,表示私有,这在Python中是约定俗成的
# 例如:from module import * 不会导入一个以下划线打头的名称
#######################################################################
# 2.5 类的命名空间
# 在class语句中定义的代码都在一个特殊的命名空间内执行的,而类的所有成员都可以访问这个命名空间
# 类定义其实就是要执行的代码段
# 定义一个计算类的实例数量
class MemberConter:
member = 0
def init(self):
MemberConter.member+=1
m1 = MemberConter()
m1.init()
m2 = MemberConter()
m2.init()
print(m1.member,m2.member)
print()
m1.member = 'Tom'
print(m1.member,m2.member)
print()
# 理解:新值被写入m1的一个属性number中,这个属性遮住了类级属性,有点类似于函数中的局部变量和全局变量的关系
#######################################################################
# 2.6 指定超类(基类)
# 指定超类,可以在class语句中的类名后加上超类名,并用括号括起来
class Filter:
def init(self):
self.blocked = []
def filter(self, seq):
return [x for x in seq if x not in self.blocked]
class SPAMFilter(Filter): # SPAMFilter 是Filter的一个子类
def init(self): # 重写超类的init方法
self.blocked = ['SPAM']
f = Filter()
f.init()
print(f.filter([1, 2, 3, 'SPAM']))
print()
s = SPAMFilter()
s.init()
print(s.filter(['SPAM','SPAM','!','2','SPAM']))
print()
# Filter类的用途在于可用于其他类(例如将'SPAM'从序列中过滤掉的SPAMFilter类)的基类
# SPAMFilter类定义要点
# 1.以提供新定义的方式重写了Filter类中init的定义
# 2.直接从Filter类继承了方法filter的定义,因此无需重新编写其定义
# 第二点说明继承很有用,可以创建大量不同的过滤类,它们都是从Filter类派生而来的,并且都使用已编好的方法filter
#######################################################################
# 2.7 深入探讨继承
# issubclass 判断一个列是否为另一个类的子类
print(issubclass(SPAMFilter,Filter))
print()
# 如果想知道一个类的基类 可通过__base__来访问
print(SPAMFilter.__bases__)
print()
# isinstance 判断对象是否是特定类的实例 type()
s = SPAMFilter()
print(isinstance(s, SPAMFilter))
print(isinstance(s, Filter))
print()
# s 是SPAMFilter类的对象,也是Filter的对象
# 如果想知道哪个对象属于哪个类,可使用属性__class__
print(s.__class__)
print(type(s))
print()
#######################################################################
# 2.8 多个超类
# 一个类可以继承于多个超类 这被称为多重继承
class Calculator:
def calculate(self, expression):
self.value = eval(expression)
class Talker:
def talk(self):
print('Hi, The value is', self.value)
class TalkingCalculator(Calculator, Talker):
pass
tc = TalkingCalculator()
tc.calculate('1+4+5')
tc.talk()
print()
# 如果多个超类以不同的方式实现了同一个方法(即有多个同名方法),必须在class语句中小心排列超类的顺序
# 因为位于前面的超类的方法会覆盖位于后面的超类的同名方法
# 多个超类的超类相同时,查找特定方法或属性时访问超类的顺序称为方法解析顺序
#######################################################################
# 2.9 接口和内省
# 在处理多态对象,你只关心其接口(协议)--对外暴露的方法和属性。
# 在python中,不显示的指定对象必须包含哪些方法才能用作参数。都是假定对象可以完成任务,如果不能完成,程序失败
# hasattr 判断对象是否有特定的属性或方法
print(hasattr(tc, 'talk'))
print(hasattr(tc, 'foot'))
print()
# 检查对象某个属性是否可调用callable getattr可以在获取指定属性不存在时使用默认值
print(callable(getattr(tc, 'talk', None)))
print(callable(getattr(tc, 'fnord', None)))
print()
# 设置对象的属性
setattr(tc, 'name', 'Tana')
print(tc.name)
print()
# 查看对象存储的所有值,可通过其__dict__属性
print(tc.__dict__)
print()
#######################################################################
# 2.10 抽象基类 abc模块
# 抽象基类是不能(至少不应该)实例化的类,其职责是定义子类应该实现的一组抽象方法
# 抽象类最重要的特征是不能实例化,实例化报错
from abc import ABC, abstractmethod
class Talker(ABC):
@abstractmethod
def talk(self):
pass
# 形如@this的东西被称为装饰器
# @abstractmethod 来将方法标记为抽象的,在子类必须实现的方法
# 如果子类也没有实现超类的抽象方法,子类也是抽象类,不能实例化
class Knigget(Talker):
pass
# a = Knigget() # 报错 抽象类不能实例化
class Knigget1(Talker):
def talk(self):
print('Knigget')
k = Knigget1()
k.talk()
print()
# 可以将某一个类注册为另一个类 register
class Herring:
def talk(self):
print('Herring')
h = Herring()
print(isinstance(h,Talker))
Talker.register(Herring)
print(isinstance(h, Talker))
def talk(a):
if isinstance(a, Talker):
a.talk()
talk(h)
print()
# 但这样做存在一个缺点 就是直接从抽象基类派生的保障没有啦
class Clam:
pass
Talker.register(Clam)
c = Clam()
print(isinstance(c, Talker))
# c.talk() 报错
# 3. 关于面向对象设计的一些思考
# ① 将相关的东西放在一起,如果一个函数操作一个全局变量,最好将他们放到一个类的属性和方法
# ② 不要让对象之间过于亲密,方法只应该关心所属实例的属性。对于其他实例的状态,让他们自己去管理
# ③ 慎用继承,尤其多重继承
# ④ 保持简单,让方法短小紧凑
Python 类
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 当子类继承父类的一些方法并且子类已经覆盖此方法时,我们如何调用父类中的函数?这里提供两种调用方式: 通过在子类中实...