URLhttps://learnscript.net/zh/python/classes/
    复制链接转到说明  示例

    Python 类介绍,以及定义和使用类

    我被代码海扁署名-非商业-禁演绎
    阅读 13:20·字数 4005·更新 

    前提

    阅读本节的前提是已经掌握类的相关概念,你可以查看编程教程面向对象编程,类,实例介绍一节来了解他们。

    定义 Python 类

    在 Python 中,类通常被定义在模块中,其语法的基本形式如下。

    class <classname>:
        <docstring>
        <block>

    classname 部分

    classname为类的名称,他需要符合 Python 的标识符规范,不能使用关键字或保留关键字。

    docstring 部分

    docstring是类的文档字符串,包含了对类的说明,这并非强制性的要求,一个类可以没有文档字符串。

    block 部分

    block为类的主体代码,他和docstring都需要使用某种空白字符进行缩进,以表示其归属于类。

    Python 类的特性

    与模块类似,在类中定义的变量(字段),属性,方法(函数)等内容,被称为特性(Attribute)。特性可通过形式类似于c.namec.name=value的表达式进行访问,其中c为类或对象(类的实例),name为特性(名称,标识符),value为特性的新值。

    当然,类的特性可以被称呼为变量,方法,属性,这并没有什么问题。

    下面是一个简单的类Apple,包含变量和静态方法。

    apple.py
    # 一个简单的类 Apple
    class Apple:
    	# 变量 variety
    	variety = '普通苹果'
    	# 静态方法 show
    	@staticmethod
    	def show():
    		print(Apple.variety)
    
    # 为特性 variety 赋值 Apple.variety = '石头苹果' # 调用 show 方法 Apple.show()
    石头苹果

    Python 的类特性和实例特性

    在 Python 中,类的特性分为类特性和实例特性,类特性直接在类中定义,或通过表示类的参数(一般约定为cls)来定义,而实例特性则需要通过实例,或表示实例的参数(一般约定为self)来定义。

    类特性可通过类或表示类的参数(一般约定为cls),以及实例或表示实例的参数(一般约定为self)来访问,而实例特性则只能通过实例或表示实例的参数来访问。

    为类或实例添加暂时特性

    在没有限制的情况下,一个类或实例可以添加暂时存在的特性,只需要使用形式为c.name=value的表达式即可,其中c为类或实例,name为添加的特性(名称,标识符),value为特性的值。

    如何查看类或实例的所有特性?

    通过类,实例,对象的特殊特性__dict__,你可以查看其对应的所有特性,包括私有特性和暂时特性在内。__dict__是一个字典对象,其中键值对的键表示特性的名称,键值对的值表示特性的具体内容。

    需要指出的是,类的__dict__与实例的__dict__中的键值对不会重叠,类的__dict__仅包含类特性,实例的__dict__仅包含实例特性,不过,不排除存在分别归属于类和实例的同名特性。

    我们调整之前的示例,为类Apple添加构造器以定义实例变量weight,并通过类添加暂时类变量price,通过实例添加暂时实例变量price,然后输出显示Apple类和实例的__dict__特性。

    apple.py
    # 一个简单的类 Apple
    class Apple:
    	# …
    	# 构造器
    	def __init__(self, w):
    		# 通过表示实例的 self 定义了实例变量 weight
    		self.weight = w
    # …
    # 为 Apple 类添加一个类变量,然后显示 Apple 类的所有特性
    Apple.price = 10
    print(Apple.__dict__)
    # 为实例添加一个实例变量,然后显示实例的所有特性
    apple = Apple(100)
    apple.price = 30
    print(apple.__dict__)
    {'__module__': '__main__', 'variety': '石头苹果', 'show': <staticmethod(<function Apple.show at >)>, '__init__': <function Apple.__init__ at >, '__dict__': <attribute '__dict__' of 'Apple' objects>, '__weakref__': <attribute '__weakref__' of 'Apple' objects>, '__doc__': None, 'price': 10}
    {'weight': 100, 'price': 30}

    不能通过实例来直接赋值修改类特性

    你可以通过实例或表示实例的参数(比如self)来读取类特性,但无法进行赋值操作,因为赋值操作将被认为是向实例增加新的特性,这类似于试图在函数中直接赋值模块定义的变量。

    在下面的代码中,书写apple.variety等同于读取Apple.variety,书写apple.variety='超大苹果'等同于为实例apple添加实例变量varietyApple.variety不会被修改。

    apple.py
    # …
    # 创建 Apple 类的实例
    apple = Apple(30)
    # 通过实例访问类变量 variety
    print(apple.variety)
    
    # 下面的赋值语句将为实例定义新的实例变量 variety apple.variety = '超大苹果' # 因此,类变量 variety 并没有变化 print(Apple.variety)
    石头苹果
    石头苹果

    定义 Python 类的变量

    类的变量(字段)分为类变量和实例变量,他是类的特性之一,你可以通过以下形式来定义类变量或实例变量,其中,cls为表示类的参数,self为表示实例的参数。

    [cls|self.]<variablename>=<value>

    variablename 部分

    variablename为变量名称,他需要符合 Python 的标识符规范,不能使用关键字或保留关键字。

    value 部分

    value为变量对应的值。

    student.py
    # 一个表示学生的类 Student
    class Student:
    	# 类变量 count
    	count = 0
    	# 构造器
    	def __init__(self, n, a):
    		# 实例变量 name,age
    		self.name = n
    		self.age = a

    定义 Python 类的方法

    类的方法(函数)是类的特性之一,他与模块中的函数有相似之处,可通过如下形式进行定义,其中,@classmethod表示定义类方法,@staticmethod表示定义静态方法。

    [@classmethod|@staticmethod]
    def <methname>(<parameterlist>)
        <block>

    methname 部分

    methname为方法名称,他需要符合 Python 的标识符规范,不能使用关键字或保留关键字。

    parameterlist 部分

    parameterlist是方法的参数列表,他定义了方法的所有参数,参数之间使用,进行分隔。

    block 部分

    block为方法的主体代码,需要使用某种空白字符进行缩进,以表示其归属于方法。

    如果未指定修饰符@classmethod@staticmethod,则定义的方法被称为实例方法,其第一个参数一般命名为self,表示实例本身,通过该参数可读取写入实例特性,或读取类特性。当通过实例调用实例方法时,需要省去self参数,当通过类调用实例方法时,需要给出self参数。

    如果指定了修饰符@classmethod,则定义的方法为类方法,其第一个参数一般命名为cls,表示类本身,通过该参数可以访问类特性,但不能访问实例特性。无论是通过实例还是类,调用类方法时都需要省去cls参数。

    如果指定了修饰符@staticmethod,则定义的方法为静态方法,静态方法不像实例方法或类方法一样拥有特殊参数,因此他不能通过特殊参数来访问实例特性或类特性。

    直接定义在类中的方法均为类特性

    事实上,直接定义在类中的方法均为类特性,而非实例特性,无论这些方法被称为实例方法,类方法还是静态方法,他们之间的主要区别在于,首个参数表示的是实例还是类,或均不表示。

    也正因为都是类特性,实例方法,类方法,静态方法既可以通过 实例调用,也可以通过类调用。

    函数

    想要深入了解 Python 函数,你可以查看Python 函数,参数,返回值介绍,以及函数的定义和调用一节。

    下面,我们为之前的Student类增加一些方法,并分别通过类或实例来调用他们。

    student.py
    # 一个表示学生的类 Student
    class Student:
    	# …
    	# 实例方法 info
    	def info(self):
    		print(f'{self.name} {self.age}')
    
    # 类方法 show @classmethod def show(cls): # 通过参数 cls 读取类变量 count print(f'一共 {cls.count} 个学生') # 静态方法 set_count @staticmethod def set_count(c): # 只能通过类访问类变量 Student.count = c print(f'学生数量被设置为 {Student.count}')
    student = Student('小小', 13) # 调用实例方法 info student.info() Student.info(student) # 调用静态方法 set_count student.set_count(-100) Student.set_count(100) # 调用类方法 show student.show() Student.show()
    小小 13
    小小 13
    学生数量被设置为 -100
    学生数量被设置为 100
    一共 100 个学生
    一共 100 个学生

    定义 Python 类的私有特性

    无论是类特性还是实例特性,如果标识符以__开头,则这些特性即为私有特性,只能在定义他们的类中访问,不能在外部或派生类中访问。

    类的私有特性标识符会自动增加前缀

    __开头的私有特性,其标识符会自动增加特定前缀,其内容为_与类名称的组合,这一现象可通过类或实例的__dict__特性来观察。标识符的改动仅涉及定义特性的类,这也就是无法在外部或派生类中使用私有特性的原因,因为你在访问一个并不存在的内容。

    当然,在了解以上规则后,私有特性可能变得不再私有,只需要采用具有特定前缀的标识符进行访问即可。

    下面的类Teacher定义了两个私有的实例变量,他们的标识符自动添加了前缀_Teacher

    teacher.py
    # 一个表示教师的类 Teacher
    class Teacher:
    	# 构造器
    	def __init__(self, n, a):
    		# 私有实例变量 __name,__age
    		self.__name = n
    		self.__age = a
    
    teacher = Teacher('隐者', 30) # 显示 Teacher 实例的所有特性 print(teacher.__dict__) # 使用特殊方式访问私有变量 __name print(teacher._Teacher__name)
    {'_Teacher__name': '隐者', '_Teacher__age': 30}
    隐者

    定义 Python 类的构造器

    类的构造器是一个名为__init__的实例方法,与其他实例方法一样,__init__方法的第一个参数一般命名为self,表示实例自身,其余参数可用于初始化实例变量或执行其他操作,就如同Student类所作的那样。

    当然,在官方文档中,并没有构造器这样的说法,__init__的含义仅为初始化,他在实例创建后被调用。

    创建 Python 类的实例

    要创建类的实例,你需要使用类名称和()()包含了一组参数,这些参数一般与__init__方法的参数一致(需要省去self)。比如,之前示例中使用Student('小小',13)创建了Student类的实例。

    如何查看实例对应的类型?

    通过实例(对象)的__class__属性(Property),可以获取该实例对应的类型(类)信息,__class__属性的返回值是一个type对象。

    对于已定义的类来说,__class__属性的返回值显示为<class 'type'>,这表示已定义的类可被视为实例,其类型是type

    student.py
    # …
    # 获取 Student 类和之前创建的实例 student 的类型信息
    print(student.__class__)
    print(Student.__class__)
    <class '__main__.Student'>
    <class 'type'>

    Python 类的命名空间

    理所当然的,类应该拥有自己的命名空间,以避免类所拥有的特性的标识符与其他标识符冲突。

    命名空间,作用域

    想要深入了解命名空间和作用域,你可以查看编程教程命名空间,作用域介绍一节。

    Python 类的文档字符串

    与函数和模块类似,类也具有存储在__doc__中的文档字符串,他是字符串字面量,是类的第一行有效代码,可以采用紧密相邻或加入空白的方式进行拼接,不包含需要运算的内容或操作。

    hello.py
    # 一个奇怪的类
    class Hello:
    	"""你好啊,"""'Python!'

    Python 嵌套类

    嵌套类是定义在另一个类,函数或方法中的类。由于作用域的一般性原则,被定义的嵌套类的可访问性,等同于同一命名空间中定义的变量。

    下面定义的嵌套类World,其可访问性等同于Hello中的类变量。

    hello.py
    # 一个奇怪的类
    class Hello:
    	# …
    	# 一个奇怪的嵌套类
    	class World:
    		pass

    内容分类

    源码

    src/zh/classes·codebeatme/python·GitHub