python——再谈抽象

主要学习如何创建对象,多态、封装、方法、属性、超类和继承。

一、对象魔法

在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法。
优点:

  • 多态:可对不同类型的对象执行相同的操作。
  • 封装:可对外部隐藏有关对象工作原理的细节。
  • 继承:可基于通用类创建出专用类。

1.1多态
无需知道对象是什么样的就能对其执行操作,这就是多态在起作用。
1.2封装
与多态不同,多态让你无需知道对象1所属的类就能调用其方法,而封装让你无需知道对象的构造就能使用它。
1.3继承
可以避免多次输入同样的代码

二、类

类——一种对象。每个对象都属于特定的类,并被称为该类的实例。
一个类的对象为另一个对象的子集时,前者是后者的子类,后者是前者的超类。因此“云雀”是“鸟类”的子类,而“鸟类”是“云雀”的超类。

2.1创建自定义类
如果没有self,所有的方法都无法访问对象本身——要操作的属性所属的对象。

class Person:
    # 其中self指向对象本身
    def set_name(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def greet(self):
        print("Hello, world! I'am {}".format(self.name))


foo = Person()
bar = Person()
foo.set_name('leo')
bar.set_name('zu')
foo.greet()
bar.greet()
# Hello, world! I'am leo
# Hello, world! I'am zu

2.2属性、函数和方法
方法和函数的区别表现在提到的参数self上。方法将其第一个参数关联到它所属的实例,因此无需提供这个参数。
因此无需提供这个参数,无疑可以将属性关联到一个普通函数,但这样就没有特殊的self参数了。

class Class:
    def method(self):
        print('I have a self')


def function():
    print("I don't")


instance = Class()
instance.method()
instance.method = function
instance.method()
# I have a self
# I don't

完全可以让另一个变量指向同一个方法

class Class:
    def method(self):
        print('I have a self')


instance = Class()
instance.method()
a = instance.method
a()
# I have a self
# I have a self

2.3隐藏,不能从外部访问类内的成员变量
默认情况下,可从外部访问对象的属性。
这违反了封装原则,应该对外部完全隐藏对象的状态(不能从外部访问类内的成员变量)。

为了避免这种情况,可将属性定义为私有
私有属性不能从对象外部访问,而只能通过存取器方法(如get_name和set_name)来访问。
python没有为私有属性提供直接的支持,而是要求程序员知道在什么情况下从外部修改属性是安全的。
要让方法或属性成为私有的,只需要让其名称以两个下划线打头即可。

class Secretive:

    def __inaccessible(self):
        print("Bet you can't see me...")

    def accessible(self):
        print("The secret message is:")
        self.__inaccessible()


s = Secretive()
# s.__inaccessible()
# AttributeError: 'Secretive' object has no attribute '__inaccessible'
s.accessible()
# The secret message is:
# Bet you can't see me...

s = Secretive()
s._Secretive__inaccessible()  # 从类外访问私有方法
# Bet you can't see me...

在类定义中,对所有以两个下划线打头的名称都进行转换,即在开头加上一个下划线和类名。
如Secretive._Secretive__inaccessible()
只要知道这种幕后处理手法,就能从类外访问私有方法,然而不应该这样做。

2.4类的命名空间
定义类时情况:在class语句中定义的代码都是在一个特殊的命名空间(类的命名空间)内执行的,而类的所有成员都可访问这个命名空间。

2.5指定超类
子类扩展了超类的定义,要指定超类,可在class语句中的类名后加上超类名,并将其用圆括号括起来。

# 定义一个超类
class Filter:
   pass

# 定义一个子类,继承超类Filter 
class SampleFilter(Filter):
   pass
  1. 子类可以重写超类Filter的方法
  2. 子类可以直接继承超类的方法定义。

2.6深入讨论继承

# 要确定一个类是否是另一个类的子类
# 使用内置方法issubclass
print(issubclass(SampleFilter, Filter))  # True

# 如果你有一个类,想要知道它的超类
# 可访问其特殊属性__bases__
print(SampleFilter.__bases__)
# (<class '__main__.Filter'>,)

# 要确定对象是否是特定类的实例,可使用isinstance
s = SampleFilter()
print(isinstance(s, SampleFilter))  # True
print(isinstance(s, Filter))  # True
# 从上面可以看到,s是SampleFilter类的实例。
# 但是由于因为SampleFilter是Filter的子类,
# 所以所有SampleFilter的实例都是Filter的实例。

# 如果你想获悉对象属于哪个类,可使用属性__class__
s = SampleFilter()
print(s.__class__)  # <class '__main__.SampleFilter'>

2.7多个超类
多重继承,继承多个超类。

class Filter:
    pass


class Complex:
    pass

# 继承多个超类
class ComplexFilter(Filter, Complex):
    pass

除非到万不得已,否则应避免使用多重继承。
需要注意:如果多个超类以不同的方式实现了同一个方法(有多个同名方法),必须在class语句中小心排列这些超类,因为位于前面的方法将覆盖于后面的类的方法。

2.8接口和内省
在Python中,不显式地指定对象必须包含哪些方法才能用作参数。

class Calculator:
    def calculate(self, expression):
        # eval是计算字符串中的表达式
        self.value = eval(expression)


class Talker:
    def talk(self):
        print('Hi, my value is', self.value)


class TalkingCalculator(Calculator, Talker):
    pass


# 检查所需的方法是否存在
tc = TalkingCalculator()
print(hasattr(tc, 'talk'))  # True
print(hasattr(tc, 'sing'))  # False

# 检查属性talk是否可调用
# getattr,能够指定属性不存在时使用默认值,这里为None
print(callable(getattr(tc, 'talk', None)))  # True

2.9抽象基类
一般而言,抽象类是不能(至少是不应该)实例化的类,其职责是定义子类应实现的一组抽象方法。
Python通过引入模块abc,来为所谓的抽象基类提供了支持。

from abc import ABC, abstractmethod


class Talker(ABC):
    @abstractmethod
    def talk(self):
        pass

# 实例化抽象类,会报错
# ta = Talker()
# ta.talk()

# 假设从Talker派生出一个子类
class knigget(Talker):
    pass
# 由于没有重写方法talk,因此这个类也是抽象的。
# 重写以后,该类就可以实例化了。

形如@this的东西被称为装饰器。这里使用@abstractmethod来将方法标记为抽象的——在子类中必须实现的方法。
抽象类最重要的特征是不能实例化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值