Python面向对象总结

栏目: Python · 发布时间: 4年前

内容简介:Python 是一门完全面向对象的语言。在 Python 中,一切都是对象。从我们开始使用 Python 时,我们就已经使用了 Python 中的对象和类。Python 程序中的每一个元素都是类的一个实例,如数字、字符串、列表、字典这些元素,都是 Python 内置类对应的一个对象,甚至于使用Python 使用

Python 是一门完全面向对象的语言。在 Python 中,一切都是对象。从我们开始使用 Python 时,我们就已经使用了 Python 中的对象和类。

Python 程序中的每一个元素都是类的一个实例,如数字、字符串、列表、字典这些元素,都是 Python 内置类对应的一个对象,甚至于使用 def 关键字定义的一个函数都对应一个 function 类。

面向对象基础

Python 使用 class 关键字声明一个类。

一个典型的 Python 类主要包含以下成员:

  • 构造函数 (constructor)
  • 实例属性 (Instance Attributes)
  • 类属性 (Class Attributes)
  • 方法 (Class Attributes)

一个类也可以没有任何成员,如下面的 Car 类就没有任何成员:

class Car:
    '''This is an empty Car Class'''
    pass

下面的类则包含了实例属性、类属性、构造函数、方法等成员:

class Car:
    brand = 'BenChi'

    def __init__(self):
        self.price = 10000
        self.chair = 7

    def run(self):
        print('Run 100km Per Hour....')

构造函数

在 Python 中,构造函数是实例化一个类对象的时自动被调用的函数,类似于 Java 或 C# 中的构造函数。构造函数必须使用一个特定的名称 __init__ ,并且必须有一个固定的参数 self

Python 类中 几乎 每一个方法都要将 self 作为第一个参数,self 是调用该方法的对象的引用。其实,第一个参数的名字是任意的,并不一定要叫 self, self 只是一种约定。

注意,注意,注意: __init__ 方法并不是 Python 类构造函数,关于 Python 类的构造函数其实有很大争议,这里主要是为了介绍面向对象的概念。

下面的例子定义了一个构造函数:

class Car:
    def __init__(self):
        print('Call Constructor......')


car1 = Car()
car2 = Car()

Python 中构造函数( init )的作用定义了类实例的属性,并对实例属性进行复制。

实例属性

实例属性是与类实例绑定的属性,其定义在构造函数( init )中。

下面的例子定义了两个实例属性:

class Car:
    def __init__(self):
        self.price = 100
        self.chair = 7

类属性

类属性不同于实例属性,类属性的值被所有实例对象共享。类属性在类级别定义而不是定义在 __init__ 方法中。类属性的访问也不同于实例属性,类属性的访问是通过类名, 也可以通过实例访问。

下面例子定义了一个类属性:

class Car:
    brand = "benchi"


print(Car.brand)

通过类名修改类属性

通过类名修改类属性,那么该类所有的实例对象对应的类属性都会被修改, 如下:

class Car:
    brand = "benchi"


car1 = Car()
car2 = Car()

print('Before Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')

print('Change Class Attribute By [Class Name]')
Car.brand = 'Audi'

print('After Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')

输出:
Before Change.............
car1 brand is: benchi
car2 brand is: benchi
Change Class Attribute By [Class Name]
After Change.............
car1 brand is: Audi
car2 brand is: Audi

通过实例对象修改类属性

通过实例对象修改类属性,并不会影响其他对象类属性的值,他仅仅影响该实例对象自己类属性的值,如下:

class Car:
    brand = "benchi"


car1 = Car()
car2 = Car()

print('Before Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')

print('Change Class Attribute By [Object]')
car1.brand = 'Audi'
car2.brand = 'KaYan'

print('After Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')
print(f'Car brand is: {Car.brand}')

输出:

Before Change.............
car1 brand is: benchi
car2 brand is: benchi
Change Class Attribute By [Object]
After Change.............
car1 brand is: Audi
car2 brand is: KaYan
Car brand is: benchi

类方法

在一个类中,可以定义尽可能多的类方法,一般情况下,类方法的第一个参数都是 self

下面的类就定义了一个类方法:

class Car:
    brand = "benchi"

    def run(self):
        print('Run......')

面向对象之封装

面向对象语言,如Java、C++等,使用 publicprotectedprivate 等关键字来控制对类资源的访问。

  • 类的 private 成员仅能在类内部进行访问,其他任何地方都不能访问,包括其子类。

  • 类的 protected 成员可以在类内部和其子类中访问。

  • 类的 public 成员可以在任何地方进行访问。

Python没有使用关键字机制来限制对类成员方法和类成员属性的访问,Python规定了一种约定,在类方法或者类成员前加 _ (下划线)或者 __ (双下划线)来模拟 private 或者 public 访问修饰期的功能。

public成员

Python中的所有成员默认都是 public 属性,可以在任何地方访问。

如下代码:

class Car:
    def __init__(self, brand, price):
        self.brand = brand
        self.price = price

    def run(self):
        print('Run......')


brand = 'Audi'
price = 10000
car = Car(brand, price)

# 访问类属性
print(car.brand)
print(car.price)

# 访问类方法
car.run()

输出结果:
Audi
10000
Run......

protected成员

Python约定,如果类成员前加了单个下划线 _ , 则类成员为protected成员。

class Car:
    def __init__(self, brand, price):
        self._brand = brand
        self._price = price

    def _run(self):
        print('Run......')


brand = 'Audi'
price = 10000
car = Car(brand, price)

# 访问protected属性
print(car._brand)
print(car._price)

# 修改protected属性
car._price = 20000
print(car._price)

# 访问类方法
car._run()

输出结果:
Audi
10000
20000
Run......

使用单下划线的方式将属性声明为 protected , 并不能真正起到作用,它仅仅是一种约定。

private成员

Python约定,如果类成员前加了双下划线 __ , 则类成员为private成员。

如下代码:

class Car:
    def __init__(self, brand, price):
        self._brand = brand
        self._price = price

    def __run(self):
        print('Run......')


# 访问类方法
car._run()  # 程序报错,'Car' object has no attribute '_run'

面向对象之继承

在面向对象编程中,继承是达到代码重用目的的一种方式。在继承中,子类可以使用其父类的一部分代码。

继承的基本使用

下面先创建一个父类, 代码如下:

class Fish:
    def __init__(self, first_name, last_name="Fish",
                 skeleton="bone", eyelids=False):
        self.first_name = first_name
        self.last_name = last_name
        self.skeleton = skeleton
        self.eyelids = eyelids

    def swim(self):
        print("The fish is swimming.")

    def swim_backwards(self):
        print("The fish can swim backwards.")

接下来,创建一个没有任何方法和属性的子类,代码如下:

class Trout(Fish):
    pass

Python类继承的语法是在定义类的时候,传入父类的名字作为参数

由于 Trout 类继承了 Fish 类, Trout 类就是 Fish 类的子类, Trout 类的对象就可以调用其父类的所有方法,代码如下:

terry = Trout("Terry")
print(terry.first_name + " " + terry.last_name)
print(terry.skeleton)
print(terry.eyelids)
terry.swim()
terry.swim_backwards()

输出:

Terry Fish
bone
False
The fish is swimming.
The fish can swim backwards.

接下来,再创建另一个子类,该子类有自己的方法:

class Clownfish(Fish):

    def live_with_anemone(self):
        print("The clownfish is coexisting with sea anemone.")

创建 Clownfish 的一个对象,并调用其方法:

class Clownfish(Fish):

    def live_with_anemone(self):
        print("The clownfish is coexisting with sea anemone.")

casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()

输出:
Casey Fish
The fish is swimming.
The clownfish is coexisting with sea anemone.

从输出结果可以看出, Clownfish 的对象 casey 可以调用其父类的 swim() 方法和 __init__() 方法,同时可以调用它自身的 live_with_anemone() 方法。

覆盖父类方法

有时候,子类继承了父类的全部方法和属性,但是只想使用其中的一部分方法和属性,当子类定义了和父类一样的方法时,就会覆盖(override)父类的方法。

有一点需要注意的是,尽管子类覆盖了父类的方法,但是并没有产生多余的代码。

下面定义一个覆盖父类 __init__() 方法和 swim_backwards() 方法的类:

class Shark(Fish):
    def __init__(self, first_name, last_name="Shark",
                 skeleton="cartilage", eyelids=True):
        self.first_name = first_name
        self.last_name = last_name
        self.skeleton = skeleton
        self.eyelids = eyelids

    def swim_backwards(self):
        print("The shark cannot swim backwards, but can sink backwards.")

sammy = Shark("Sammy")
print(sammy.first_name + " " + sammy.last_name)
sammy.swim()
sammy.swim_backwards()
print(sammy.eyelids)
print(sammy.skeleton)

结果:
Sammy Shark
The fish is swimming.
The shark cannot swim backwards, but can sink backwards.
True
cartilage

从输出结果可以看出,子类成功覆盖了父类的方法。

super()函数

如果子类覆盖了父类的方法,同时又想使用父类的方法,可以使用 super() 函数。

super() 函数经常在 __init__() 方法中被使用。

修改一下上文所提到的 Trout 类,代码如下:

class Trout(Fish):
    def __init__(self, water = "freshwater"):
        self.water = water
        super().__init__(self)


terry = Trout()

terry.first_name = "Terry"

print(terry.first_name + " " + terry.last_name)
print(terry.eyelids)

print(terry.water)

terry.swim()

输出:

Terry Fish
False
freshwater
The fish is swimming.

从输出结果可以看出,使用 super() 函数成功调用了父类被子类覆盖的方法。

多重继承

多重继承即一个类可以继承多个类。

多重继承基本语法如下:

class Coral:

    def community(self):
        print("Coral lives in a community.")


class Anemone:

    def protect_clownfish(self):
        print("The anemone is protecting the clownfish.")


class CoralReef(Coral, Anemone):
    pass

总结

本篇文章总结了Python面向对象的基本概念及基本使用方法,弥补自己在Python方面面向对象方法的不足。

参考


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

组合数学

组合数学

(美)Richard A. Brualdi / 冯速 等 / 机械工业出版社 / 2012-5 / 69.00元

本书是系统阐述组合数学基础、理论、方法和实例的优秀教材,出版三十多年来多次改版,被MIT、哥伦比亚大学、UIUC、威斯康星大学等众多国外高校采用,对国内外组合数学教学产生了较大影响,也是相关学科的主要参考文献之一。 本书侧重于组合数学的概念和思想,包括鸽巢原理、计数技术、排列与组合、P條ya计数法、二项式系数、容斥原理、生成函数和递推关系以及组合结构(匹配、试验设计、图)等,深入浅出地表达了......一起来看看 《组合数学》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具