likes
comments
collection
share

非常详细非常零基础的Python教程:面向对象部分内容

作者站长头像
站长
· 阅读数 16

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情

类和对象

面向对象

面向对象编程可以更好的模拟现实中事物(对象),并把对象具有的特征、行为封装起来。举个例子来说:绿色小乌龟爬呀爬。这个你看到的绿色小乌龟就是一个对象,爬是它的行为,绿色是它的属性、特征。面向对象编程会将乌龟的属性和行为封装起来,抽象成一个(乌龟)类。通过这个类创建一个对象,就是小乌龟了。代码举例:

#######乌龟类######
class WuGui:
  color = "绿色"
  def crawl(self):
    print("爬呀爬")
#######小乌龟(对象)###
greenWuGui = WuGui()

除了面向对象,还有一种叫面向过程,如C语言,它里面是不含对象这个概念的。

类的定义/对象的创建与使用

语法:

class 类名:
  类的属性(>=0个属性)...
  类的方法(>=0个方法)...

属性就是像颜色、身高、体重这些名词,体现到代码上就是变量。方法就是行为,像爬、吃饭这些动作,体现到代码上就是方法。举例:

class TheFirstDemo:
    # 下面定义了一个类属性
    add = 'http://c.biancheng.net'
    # 下面定义了一个say方法
    def say(self, content):
        print(content)

类的构造方法

在创建类时,我们可以手动添加一个 __init__()方法,该方法是一个特殊的类实例方法,称为构造方法(或构造函数)。手动创建的构造方法语法格式如下:

def __init__(self,...):  
    代码块

注意是两个下划线,左边两个右边两个__init__()方法可以包含多个参数,但必须包含一个名为 self 的参数,且必须作为第一个参数。也就是说,类的构造方法最少也要有一个 self 参数。举例:

####这个类的构造函数只有self一个参数
class TheTwoDemo:
    #构造方法
    def __init__(self):
        print("调用构造方法")
    # 下面定义了一个类属性
    add = 'http://c.abc.net'
    # 下面定义了一个say方法
    def say(self, content):
        print(content)
####这个类的构造函数有self、name、add三个参数
class CLanguage:
    name = "CCC"
    add = "http://c.abc.net"
    '''这是一个学习Python定义的一个类'''
    def __init__(self,name,add):
        self.name = name
        self.add = add
        print(name,"的网址为:",add)

这个self.name后面在对象的使用部分讲。

注意,即便不手动为类添加任何构造方法,Python 也会自动为类添加一个仅包含 self 参数的构造方法(python中默认构造方法)。另外,类在实例化的时候会先调用类的构造方法。

类的实例化

类的实例化意思就是创建对象,语法如下:

类名(参数)

定义类时,如果没有手动添加 __init__() 构造方法,又或者添加的 init() 中仅有一个 self 参数,则创建类对象时的参数可以省略不写。如上面代码TheTwoDemo类的实例化举例:(类的构造方法小节的代码)

demo1 = TheTwoDemo()

针对于手动添加init构造方法,且参数除了self还有其他参数,如上面代码Clanguage类的实例化举例(类的构造方法小结的代码)

clanguage = CLanguage("CCCC","http://c.abc.net")

在上面的程序(类的构造方法小节)中,由于构造方法除 self 参数外,还包含 2 个参数,且这 2 个参数没有设置默认参数,因此在实例化类对象时,需要传入相应的 name 值和 add 值(self 参数是特殊参数,不需要手动传值,Python 会自动传给它值)。

对象的使用
类对象名.变量名
类对象名.方法名

举例:

#######类的定义############
class CLanguage:
    name = "CCCC"
    add = "http://c.abc.net"
    '''这是一个学习Python定义的一个类'''
    def __init__(self,name,add):
        self.name = name
        self.add = add
        print(name,"的网址为:",add)
    # 下面定义了一个say实例方法
    def say(self, content):
        print(content)
########实例化##############
clanguage = CLanguage("CCCC","http://c.abc.net")
###########对象的使用###############
print(clanguage.name) #输出name的值
clanguage.say("人生苦短,及时行乐")
clanguage.name = "python" #修改实例变量
print(clanguage.name)

在类方法内部以“self.变量名”的方式定义的变量称为实例变量,特点是只作用于调用方法的对象(就是上述代码中clanguage这个对象,而改不了类模版中的类属性),实例变量只能通过对象名访问,无法通过类名访问。

运行结果:(斜杠开头的是注释部分)

//实例化会先运行构造函数,执行构造函数结果:
CCCC 网址为: http://c.abc.net
//下面是运行print(clanguage.name)的结果
CCCC
//调用claguage.say方法后的执行结果
人生苦短,及时行乐
//修改实例变量后的输出
python

self的理解

self 参数的具体作用是什么呢?打个比方,如果把类比作造房子的图纸,那么类实例化后的对象是真正可以住的房子。根据一张图纸(类),我们可以设计出成千上万的房子(类对象),每个房子长相都是类似的(都有相同的类变量和类方法),但它们都有各自的主人,那么如何对它们进行区分呢?

当然是通过 self 参数,它就相当于每个房子的门钥匙,可以保证每个房子的主人仅能进入自己的房子(每个类对象只能调用自己的类变量和类方法)。也就是说,同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,换句话说,Python 会自动绑定类方法的第一个参数指向调用该方法的对象。如此,Python解释器就能知道到底要操作哪个对象的方法了。

类变量和实例变量(类属性和实例属性)

前面章节提到过,在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性又可细分为以下 3 种类型:

  1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
  2. 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
  3. 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。

不仅如此,类方法也可细分为实例方法、静态方法和类方法,后续章节会做详细介绍。

类变量

举例:

class CLanguage :
    # 下面定义了2个类变量
    name = "CCCC"
    add = "http://c.abc.net"
    # 下面定义了一个say实例方法
    def say(self, content):
        print(content)

上面程序中,name 和 add 就属于类变量。类变量的特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的。类方法的调用方式有 2 种,既可以使用类名直接调用,也可以使用类的实例化对象调用。

不推荐使用类名调用类变量来修改类变量,因为这样做会影响所有的实例化对象。通过类名修改类变量会作用到所有实例化对象身上,会修改所有实例化对象。

实例变量(实例属性)

实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。

class CLanguage :
    def __init__(self):
        self.name = "CCCC"
        self.add = "http://c.abc.net"
    # 下面定义了一个say实例方法
    def say(self):
        self.catalog = 13

代码中self.name、self.add、self.catalog都是实例变量。其中,由于 init() 函数在创建类对象时会自动调用,而 say() 方法需要类对象手动调用。因此,CLanguage 类的类对象都会包含 name 和 add 实例变量,而只有调用了 say() 方法的类对象,才包含 catalog 实例变量。添加下面代码:

clang = CLanguage()
print(clang.name)
print(clang.add)
#由于 clang 对象未调用 say() 方法,因此其没有 catalog 变量,下面这行代码会报错
#print(clang.catalog)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
#只有调用 say(),才会拥有 catalog 实例变量
clang2.say()
print(clang2.catalog)

运行结果:

CCCC
http://c.abc.net
CCCC
http://c.abc.net
13
局部变量

除了实例变量,类方法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如:

class CLanguage :
    # 下面定义了一个say实例方法
    def count(self,money):
        sale = 0.8*money
        print("优惠后的价格为:",sale)
clang = CLanguage()
clang.count(100)

程序中的sale就是局部变量。通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。

实例方法、静态方法、类方法

实例方法

在类中默认定义的方法就是实例方法,它的特点是最少包含一个self参数,用于绑定调用此方法的实例对象。实例方法通常会用类对象直接调用。 如上面局部变量部分程序的clang.count(100)。

类对象调用实例方法就不举例了(clang.count(100)就是类对象调用实例方法),举例使用类调用实例方法的做法:

######定义了一个类#########
class CLanguage:
    def info(self):
        print("我正在学 Python")
###########用类名调用实例方法########
clang = CLanguage()
#通过类名直接调用实例方法
CLanguage.info(clang)
类方法

类方法与实例方法相似,最少也包含一个参数(类方法中通常命名为cls,当然也可以随便起名),Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。

“无需显式”意思就是传不传都行。

和实例方法最大的不同在于,类方法需要使用@classmethod修饰符进行修饰,例如:

class CLanguage:
    #类构造方法,也属于实例方法
    def __init__(self):
        self.name = "CCCC"
        self.add = "http://c.abc.net"
    #下面定义了一个类方法
    @classmethod
    def info(cls):
        print("正在调用类方法",cls)

注意,如果没有 @classmethod,则 Python 解释器会将 fly() 方法认定为实例方法,而不是类方法。

类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)。例如,在上面 CLanguage 类的基础上,在该类外部添加如下代码:

#使用类名直接调用类方法
CLanguage.info()
#使用类对象调用类方法
clang = CLanguage()
clang.info()

运行结果:

正在调用类方法 <class '__main__.CLanguage'>
正在调用类方法 <class '__main__.CLanguage'>
静态方法

静态方法其实就是普通的函数,但是需要加上@staticmethod注解。如:

class CLanguage:
    @staticmethod
    def info(name,add):
        print(name,add)

静态方法的调用,既可以使用类名,也可以使用类对象,例如:

#使用类名直接调用静态方法
CLanguage.info("CCCC","http://c.abc.net")
#使用类对象调用静态方法
clang = CLanguage()
clang.info("Python教程","http://c.abc.net/python")
运行结果:
CCCC http://c.abc.net
Python教程 http://c.abc.net/python

在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能。

python封装

面向对象的三大特性就是封装、继承和多态。封装指的是在设计类的时候刻意的讲一些属性和方法隐藏在类的内部,这样在使用此类的时候无法以对象名.属性、对象名.方法()这种形式来调用这些属性,而只能用未隐藏的类方法间接操作这些隐藏的属性和方法。就好比电脑,电脑里面的软件我们只能通过键盘或鼠标来打开,而无法直接打开。我们不关心电脑里面的东西怎么做的,只要用好键盘鼠标就行了。

如何使用封装

和其它面向对象的编程语言(如 C++、Java)不同,Python 类中的变量和函数,不是公有的(公有就是都可以用,都可以访问),就是私有的(就是你的,别人看不到用不了),这 2 种属性的区别如下:

  • public:公有属性的类变量和类函数,在类的外部、类内部以及子类(后续讲继承特性时会做详细介绍)中,都可以正常访问;
  • private:私有属性的类变量和类函数,只能在本类内部使用,类的外部以及子类都无法使用。

但Python 并没有提供 public、private 这些修饰符。为了实现类的封装,Python 采取了下面的方法:

  • 默认情况下,Python 类中的变量和方法都是公有(public)的,它们的名称前都没有下划线(_);
  • 如果类中的变量和函数,其名称以双下划线“__”开头,则该变量(函数)为私有变量(私有函数) ,其属性等同于 private。

注意,Python 类中还有以双下划线开头和结尾的类方法(例如类的构造函数__init__(self)),这些都是 Python 内部定义的,用于 Python 内部调用。我们自己定义类属性或者类方法时,不要使用这种格式。

举例一:

class CLanguage :
    def setname(self, name):
        self.__name = name
    def getname(self):
        return self.__name

    def setadd(self, add):
        self.__add = add
    def getadd(self):
        return self.__add
    #定义个私有方法
    def __display(self):
        print(self.__name,self.__add)
clang = CLanguage()
clang.setname("CCCC")
clang.setadd = ("http://c.abc.net")
print(clang.getname())
print(clang.getadd())

上面程序中,CLanguage 将 name 和 add 属性都隐藏了起来,但同时也提供了可操作它们的“窗口”,也就是各自的 set和 get 方法,这些方法都是公有(public)的。我们可以通过这些get和set间接访问到这个属性。就如程序中clang.setname(“CCCC")将clang的name设置成CCCC,而对name进行了操作。

通过对 CLanguage 类进行良好的封装,使得用户仅能通过暴露的 setter() 和 getter() 方法操作 name 和 add 属性。但目前这种操作依然比较繁琐,介于此,python提供了property函数实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。

property语法:

属性名=property(fget=None, fset=None, fdel=None, doc=None)

其中,fget 参数用于指定获取该属性值的类方法,fset 参数用于指定设置该属性值的方法,fdel 参数用于指定删除该属性值的方法,最后的 doc 是一个文档字符串,用于说明此函数的作用。这里举例来改善例子一中的代码:

class CLanguage :
    def setname(self, name):
        self.__name = name
    def getname(self):
        return self.__name
    #为 name 配置 setter 和 getter 方法
    name = property(getname, setname)
    
    def setadd(self, add):
        self.__add = add
    def getadd(self):
        return self.__add
    #为 add 配置 setter 和 getter 方法
    add = property(getadd, setadd)
    
    #定义个私有方法
    def __display(self):
        print(self.__name,self.__add)
clang = CLanguage()
clang.name = "CCCC"
clang.add = "http://c.abc.net"
print(clang.name)
print(clang.add)

私有方法的调用,可以通过“公有方法调用私有方法”间接对私有方法进行调用。

python继承

继承经常用于创建和现有类功能属性类似的新类,又不想直接将现有类代码复制给新类。

举个例子,假设现有一个 Shape 类,该类的 draw() 方法可以在屏幕上画出指定的形状,现在需要创建一个 Form 类,要求此类不但可以在屏幕上画出指定的形状,还可以计算出所画形状的面积。要创建这样的类,笨方法是将 draw() 方法直接复制到新类中,并添加计算面积的方法。实现代码如下所示:

class Shape:
    def draw(self,content):
        print("画",content)
class Form:
    def draw(self,content):
        print("画",content)
    def area(self):
        #....
        print("此图形的面积为...")

更简单的方法,就是使用类的继承机制。实现方法为:让 Form 类继承 Shape 类,这样当 Form 类对象调用 draw() 方法时,Python 解释器会先去 Form 中找以 draw 为名的方法,如果找不到,它还会自动去 Shape 类中找。如此,我们只需在 Form 类中添加计算面积的方法即可,示例代码如下:

class Shape:
    def draw(self,content):
        print("画",content)
class Form(Shape):
    def area(self):
        #....
        print("此图形的面积为...")

Python 中,实现继承的类称为子类,被继承的类称为父类(也可称为基类、超类)。因此在上面这个样例中,Form 是子类,Shape 是父类。子类继承父类时,只需在定义子类时,将父类(可以是多个)放在子类之后的圆括号里即可。语法格式如下:

class 类名(父类1, 父类2, ...):
    #类定义部分

注意,如果该类没有显式指定继承自哪个类,则默认继承 object 类(object 类是 Python 中所有类的父类,即要么是直接父类,要么是间接父类)。

在python中子类可以有多个直接父类,也就是说python支持多继承,一个儿子可以有多个爸爸emm。

继承这块还有一种说法:子类继承父类,父类派生子类。

举例演示:

class People:
    def say(self):
        print("我是一个人,名字是:",self.name)
class Animal:
    def display(self):
        print("人也是高级动物")
#同时继承 People 和 Animal 类
#其同时拥有 name 属性、say() 和 display() 方法
class Person(People, Animal):
    pass
zhangsan = Person()
zhangsan.name = "张三"
zhangsan.say()
zhangsan.display()

运行结果:

我是一个人,名字是: 张三
人也是高级动物

最后提一下多继承:使用多继承经常需要面临的问题是,多个父类中包含同名的类方法,子类是从哪个父类中继承过来的,不好判断。 对于这种情况,Python 的处置措施是:根据子类继承多个父类时这些父类的前后次序决定,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法。

方法重写

在python中子类继承了父类,那么子类就拥有了父类所有的类属性和类方法。通常情况下,子类会在此基础上,扩展一些新的类属性和类方法。

但我们也可能会遇到这样一种情况,即子类从父类继承得来的类方法中,有个别的类方法并不能直接照搬父类的(个别方法不适合子类用),如果不对这部分类方法进行修改,子类对象无法使用。针对这种情况,我们就需要在子类中重写父类的方法。

举个例子,鸟通常是有翅膀的,也会飞,因此我们可以像如下这样定义个和鸟相关的类:

class Bird:
    #鸟有翅膀
    def isWing(self):
        print("鸟有翅膀")
    #鸟会飞
    def fly(self):
        print("鸟会飞")

但是,对于鸵鸟来说,它虽然也属于鸟类,也有翅膀,但是它只会奔跑,并不会飞。针对这种情况,可以这样定义鸵鸟类:

class Ostrich(Bird):
    # 重写Bird类的fly()方法
    def fly(self):
        print("鸵鸟不会飞")

可以看到,因为 Ostrich 继承自 Bird,因此 Ostrich 类拥有 Bird 类的 isWing() 和 fly() 方法。其中,isWing() 方法同样适合 Ostrich,但 fly() 明显不适合,因此我们在 Ostrich 类中对 fly() 方法进行重写。

重写,有时又称覆盖,是一个意思,指的是对类中已有方法的内部实现进行修改。

完整代码如下:

class Bird:
    #鸟有翅膀
    def isWing(self):
        print("鸟有翅膀")
    #鸟会飞
    def fly(self):
        print("鸟会飞")
class Ostrich(Bird):
    # 重写Bird类的fly()方法
    def fly(self):
        print("鸵鸟不会飞")
# 创建Ostrich对象
ostrich = Ostrich()
#调用 Ostrich 类中重写的 fly() 类方法
ostrich.fly()

运行结果:

鸵鸟不会飞

super函数

python中提供了super()函数来调用父类的构造方法。语法与举例:

super().__init__(...)

先举个多继承的例子,在例子中,定义了People、Animal、Person三个类。People类中定义了name属性、say方法,Animal中定义了food属性和display方法,Person先后继承了People和Animal两个类,最后我们执行了person继承过来的say方法和name属性,运行正常。但是如果让其去执行从Animal类中继承过来的display,就会报错。因为该方法需要用到food属性,由于 People 类的构造方法“遮蔽”了Animal 类的构造方法(让其没有看到food属性),使得在创建 per 对象时,Animal 类的构造方法未得到执行,所以程序出错。

class People:
    def __init__(self,name):
        self.name = name
    def say(self):
        print("我是人,名字为:",self.name)
class Animal:
    def __init__(self,food):
        self.food = food
    def display(self):
        print("我是动物,我吃",self.food)
#People中的 name 属性和 say() 会遮蔽 Animal 类中的
class Person(People, Animal):
    pass
per = Person("zhangsan")
per.say()
#per.display()

运行结果:

我是人,名字为: zhangsan

在子类中的构造方法中,调用父类构造方法的方式有 2 种,分别是:

  1. 类可以看做一个独立空间,在类的外部调用其中的实例方法,可以向调用普通函数那样,只不过需要额外备注类名(此方式又称为未绑定方法);
  2. 使用 super() 函数。但如果涉及多继承,该函数只能调用第一个直接父类的构造方法。

也就是说,涉及到多继承时,在子类构造函数中,调用第一个父类构造方法的方式有以上 2 种,而调用其它父类构造方法的方式只能使用未绑定方法

使用super来优化上述代码如下:

class People:
    def __init__(self,name):
        self.name = name
    def say(self):
        print("我是人,名字为:",self.name)
class Animal:
    def __init__(self,food):
        self.food = food
    def display(self):
        print("我是动物,我吃",self.food)
class Person(People, Animal):
    #自定义构造方法
    def __init__(self,name,food):
        #调用 People 类的构造方法
        super().__init__(name)
        #super(Person,self).__init__(name) #执行效果和上一行相同
        #People.__init__(self,name)#使用未绑定方法调用 People 类构造方法
        #调用其它父类的构造方法,需手动给 self 传值
        Animal.__init__(self,food)    
per = Person("zhangsan","熟食")
per.say()
per.display()

运行结果:

我是人,名字为: zhangsan
我是动物,我吃 熟食

可以看到,这里再使用display就不会报错了。

多态

类的多态特性,要满足以下 2 个前提条件:

  1. 继承:多态一定是发生在子类和父类之间;
  2. 重写:子类重写了父类的方法。

举例:

class Animal:
    def say(self):
        print("动物都有say方法")
class QingWa(CLanguage):
    def say(self):
        print("青蛙呱呱呱")
class YaZi(CLanguage):
    def say(self):
        print("鸭子嘎嘎嘎")
a = CLanguage()
a.say()
a = CPython()
a.say()
a = CLinux()
a.say()

运行结果:

动物都有say方法
青蛙呱呱呱
鸭子嘎嘎嘎嘎

可以看到,青蛙和鸭子都是动物(都继承了Animal类),叫的方式却都不同(重写了say方法),像这种就是多态。父类中定义的行为,针对不同对象都有不同的实现。

针对多态度,python中还有一种写法;

class WhoSay:
    def say(self,who):
        who.say()
class Animal:
    def say(self):
        print("动物都有say方法")
class QingWa(CLanguage):
    def say(self):
        print("青蛙呱呱呱")
class YaZi(CLanguage):
    def say(self):
        print("鸭子嘎嘎嘎")
a = WhoSay()
a.say(Animal())
a.say(QingWa())
a.say(Yazi())

运行结果:

动物都有say方法
青蛙呱呱呱
鸭子嘎嘎嘎嘎

通过给 WhoSay 类中的 say() 函数添加一个 who 参数,其内部利用传入的 who 调用 say() 方法。这意味着,当调用 WhoSay 类中的 say() 方法时,我们传给 who 参数的是哪个类的实例对象,它就会调用那个类中的 say() 方法。

枚举类

一些具有特殊含义的类,其实例化对象的个数往往是固定的,比如用一个类表示月份,则该类的实例对象最多有 12 个;再比如用一个类表示季节,则该类的实例化对象最多有 4 个。而对于这些实例化对象个数固定的类,可以用枚举类来定义。

举例定义枚举类:

from enum import Enum
class Color(Enum):
    # 为序列值指定value值
    red = 1
    green = 2
    blue = 3

如果想将一个类定义为枚举类,只需要令其继承自 enum 模块中的 Enum 类即可。 例如在上面程序中,Color 类继承自 Enum 类,则证明这是一个枚举类。

在 Color 枚举类中,red、green、blue 都是该类的成员(可以理解为是类变量)。注意,枚举类的每个成员都由 2 部分组成,分别为 name 和 value,其中 name 属性值为该枚举值的变量名(如 red),value 代表该枚举值的序号(序号通常从 1 开始)。

和普通类的用法不同,枚举类不能用来实例化对象,但这并不妨碍我们访问枚举类中的成员。访问枚举类成员的方式有多种,举例如下:

#调用枚举成员的 3 种方式
print(Color.red)
print(Color['red'])
print(Color(1))
#调取枚举成员中的 value 和 name
print(Color.red.value)
print(Color.red.name)
#遍历枚举类中所有成员的 2 种方式
for color in Color:
    print(color)

枚举类成员之间不能比较大小,但可以用 == 或者 is 进行比较是否相等:

print(Color.red == Color.green)
print(Color.red.name is Color.green.name)
->Flase
->Flase

需要注意的是,枚举类中各个成员的值,不能在类的外部做任何修改,也就是说在类外部不能这样子:Color.red = 4Python 枚举类中各个成员必须保证 name 互不相同,但 value 可以相同。

除了通过继承 Enum 类的方法创建枚举类,还可以使用 Enum() 函数创建枚举类。例如:

Enum() 函数可接受 2 个参数,第一个用于指定枚举类的类名,第二个参数用于指定枚举类中的多个成员。

from enum import Enum
#创建一个枚举类
Color = Enum("Color",('red','green','blue'))
#调用枚举成员的 3 种方式
print(Color.red)
print(Color['red'])
print(Color(1))
#调取枚举成员中的 value 和 name
print(Color.red.value)
print(Color.red.name)
#遍历枚举类中所有成员的 2 种方式
for color in Color:
    print(color)

仅通过一行代码,即创建了一个和前面的 Color 类相同的枚举类。运行程序,其输出结果为:

Color.red
Color.red
Color.red
1
red
Color.red
Color.green
Color.blue