Python基础13 面向对象--类

Python与C++、Java等众多语言一样,被视为一种面向对象的语言。

如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。 

一、类定义

一个简单的类定义如下:

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))

这里Person是类的名称。 Class语句创建独立的命名空间。

 

>>> p = Person()
>>> p.set_name('Mike')
>>> p.greet()
<__main__.Person object at 0x100614e10>
<class '__main__.Person'>
Hello, world! I'm Mike

 

每个与类相关联的方法都会自动传递出参数self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。

从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。

实际上,可以随便给这个参数命名,但鉴于它总是指向对象本身,因此习惯上将其命名为self。

self会自动传递,因此我们不需要传递它。

 

二、构造函数

类有一个名为 __init__() 的特殊方法称为构造函数,该方法在类实例化时会自动调用。

__init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上。例如:

class Person:
    def __init__(self, name):
        self.name = name
        print('__init__')
        print(self.name)

实例化Person以及输出的结果示例为:

>>> p = Person('John')
__init__
John

以self为前缀的变量可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。

self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。

 

三、属性

1、给属性指定默认值

类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = 8

2、修改属性的值

可以通过实例或者类方法对属性进行修改。

class Person:
    def __init__(self, name):
        self.name = name
        self.age = 8
        print('name:', self.name)

    def set_name(self, name):
        self.name = name
        print('name:', self.name)

p = Person('Mike')
p.name = 'Jack'
print('name:', p.name)

p.set_name('Rose')

输出结果为:

name: Mike
name: Jack
name: Rose

 

四、继承

一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。

子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

1、子类的构造函数__init__()

在子类的构造函数里,必须调用父类的构造函数,这样才能正确的初始化对象。

class Car:
    """汽车"""

    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

class ElectricCar(Car):
    """电动汽车的独特之处"""

    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)

2、子类的属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。

class ElectricCar(Car):
    """电动汽车"""

    def __init__(self, make, model, year):
        """
        电动汽车的独特之处
        初始化父类的属性,再初始化电动汽车特有的属性
        """
        super().__init__(make, model, year)
        self.battery_size = 70

    def describe_battery(self):
        print("This car has a " + str(self.battery_size) + "-kWh battery")


my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

输出结果为:

2019 Tesla Model S
This car has a 70-kWh battery

3、重写(覆盖)父类的方法

如果子类定义的方法与父类方法同名,则调用子类实例的时候Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

假设Car类有一个名叫fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此我们可以重写它。

class ElectricCar(Car):
    --snip--

    def fill_gas_tank(self):
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")

现在如果我们对电动汽车调用fill_gas_tank(),Python将忽略Car类中的方法fill_gas_tank()。

 

五、静态方法和类方法

1、静态方法

静态方法的装饰器为staticmethod。

静态方法的定义中没有参数self,可直接通过类来调用,表示该方法与具体实例无关。

class MyClass:

    @staticmethod
    def smeth():
        print("This is a static method")

可像下面这样直接使用:

>>> MyClass.smeth()
This is a static method

2、类方法

类方法的装饰器为classmethod。

类方法的定义中包含类似于self的参数,通常被命名为cls。类方法也可以通过类直接调用,参数cls将自动关联到类。

class MyClass:

    @classmethod
    def cmeth(cls):
        print("This is a class method of", cls)

可像下面这样直接使用:

>>> MyClass.cmeth()
This is a class method of <class '__main__.MyClass'>

 

六、抽象基类

抽象基类是不能(至少是不应该)实例化的类,其职责是定义子类应实现的一组抽象方法。

Python通过引入模块abc提供了官方解决方案,这个模块为抽象基类提供了支持。

下面是一个简单的示例:

 

from abc import ABC, abstractmethod


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

 

抽象类不能实例化,并且没有实现抽象方法的子类也不能实例化:

class Knigger(Talker):
    pass
>>> Talker()
    Talker()
TypeError: Can't instantiate abstract class Talker with abstract methods talk
>>> Knigger()
    Knigger()
TypeError: Can't instantiate abstract class Knigger with abstract methods talk

我们可重新编写子类,实现要求的方法:

class Knigger(Talker):
    def talk(self):
        print("Hi!")
>>> k = Knigger()
>>> k.talk()
Hi!

 

posted on 2020-03-16 14:20  麦克煎蛋  阅读(232)  评论(0编辑  收藏  举报