zoukankan      html  css  js  c++  java
  • Python 简明教程 --- 20,Python 类中的属性与方法

    微信公众号:码农充电站pro
    个人主页:https://codeshellme.github.io

    与客户保持良好的关系可以使生产率加倍。
    —— Larry Bernstain

    目录

    在这里插入图片描述

    类中的变量称为属性,类中的函数称为方法

    类中的属性分为:

    • 实例属性:对象所有,互不干扰
    • 类属性:类所有,所有对象共享

    类中的方法分为:

    • 实例方法:定义中有self 参数
    • 类方法:定义中有cls 参数,使用@classmethod 装饰器
    • 静态方法:定义中即没有self 参数,也没有cls 参数,使用@staticmethod 装饰器

    1,实例属性与类属性

    类的对象,就是类的一个实例。类的实例属性被对象所有,包含在每个对象之中,不同的对象之间,互不干扰。类的类属性被类所有,被包含在类中,是所有的类对象共享。

    在这里插入图片描述

    一般情况下,实例属性会在__init__ 方法中声明并初始化,并且使用self 来绑定。而类属性是在类作用域中被声明,并且不使用self 来绑定。

    例如下面代码中,country 为类属性,__name 为实例属性:

    #! /usr/bin/env python3
    
    class People:
    
        country = 'china'
    
        def __init__(self, name):
            self.__name = name
    

    访问实例属性时使用对象.属性名的格式,实例属性属于对象各自的,互不影响:

    >>> p1 = People('小明')
    >>> p2 = People('小美')
    >>> 
    >>> p1.get_name()
    '小明'
    >>> p2.get_name()
    '小美'
    

    类属性被所有对象共有,一旦被改变,所有对象获取到的值都会被改变。访问类属性时使用类名.属性名的格式,也可以使用对象.属性名的格式来访问:

    >>> People.country              # 用`类名.属性名`的格式访问
    'CHINA'
    >>> p1.country                  # 用`对象.属性名`的格式访问
    'china'
    >>> p2.country
    'china'
    >>> 
    >>> People.country = 'CHINA'    # 类属性的值被改变
    >>> p1.country                  # 每个对象获取到的值也会被改变
    'CHINA'
    >>> p2.country
    'CHINA'
    

    注意,在使用对象.属性名的格式访问对象时,不要以这种格式对类属性进行赋值,否则结果可能不会像你想象的一样:

    >>> p1 = People('小明')
    >>> p2 = People('小美')
    >>> People.country
    'china'
    >>> p1.country
    'china'
    >>> p2.country
    'china'
    >>> p1.country = '中国'   # 使用`对象.属性名`的格式对类对象进行赋值
    >>> p1.country           # 只有 p1.country 被改变
    '中国'
    >>> p2.country           # p2.country 没有被改变
    'china'
    >>> People.country       # People.country 也没有被改变
    'china'
    

    从上面代码中可以看到,在Python 中以对象.属性名格式对类属性进行赋值时,只有p1.country 的值被改变了,p2.countryPeople.country 的值都没有被改变。

    实际上,这种情况下,类属性的值并没有被改变,而是对象p1 中多了一个country 实例属性,此后,p1.country 访问的是p1 的实例属性,p1.country对属性country的访问屏蔽了类中的country属性,而p2.countryPeople.country 访问的依然是原来的类属性

    所以,类名.属性名对象.属性名的格式都可以访问类属性的值,但尽量避免使用对象.属性名的格式对类属性的值进行赋值,否则可能会发生混乱。

    建议:

    不管是访问还是改变类属性的值,都只用类名.属性名的格式

    2,实例方法,类方法,静态方法

    Python 类中有三种方法:

    • 实例方法
    • 类方法
    • 静态方法

    实例方法属于对象,方法中都有一个self 参数(代表对象本身)。实例方法只能由对象调用,不能通过类名访问。实例方法中可以访问实例属性和类属性。

    类方法属于类,方法中都有一个cls 参数(代表类本身)。类方法即可以通过类名访问,也可以通过对象访问,类方法中只能访问类属性,不能访问实例属性。

    注意:

    Python 解释器在构造类与对象时,是先于对象产生的。

    因此,类属性与类方法是先于实例属性与实例方法 产生的。

    所以当类方法产生时,还没有实例属性,因此,类方法中不能访问实例属性。

    静态方法中,没有self 参数,也没有cls 参数。因此,在静态方法中,即不能访问类属性,也不能访问实例属性。静态方法可以使用类名访问,也可以使用对象访问。

    在Python 中,定义类方法需要用到装饰器@classmethod,定义静态方法需要用到装饰器@staticmethod

    实例方法演示

    #! /usr/bin/env python3
    
    class People:
    
        country = 'china'
    
        def __init__(self, name):
            self.__name = name
    
        # 实例方法中有self 参数
        def instance_method_test(self):
            # 在实例方法中访问了实例属性和类属性
            print('name:%s country:%s' % (self.__name, People.country))
    

    使用:

    >>> p = People('小明')
    >>> p.instance_method_test()
    name:小明 country:china
    

    在实例方法中访问了实例属性__name和类属性country,均可以被访问。

    类方法演示

    #! /usr/bin/env python3
    
    class People:
    
        country = 'china'
    
        def __init__(self, name):
            self.__name = name
    
        # 类方法中都有cls 参数
        @classmethod
        def class_method_test1(cls):
            print('在类方法中访问类属性country:%s' % cls.country)
    
        @classmethod
        def class_method_test2(cls):
            print('在类方法中访问实例属性__name:%s' % self.__name)
    

    使用:

    >>> p = People('小明')
    >>> p.class_method_test1()         # 在类方法中访问类属性,可以
    在类方法中访问类属性country:china
    >>>
    >>> p.class_method_test2()         # 在类方法中访问实例属性,出现异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/wp/to_beijing/People.py", line 18, in class_method_test2
        print('在类方法中访问实例属性__name:%s' % self.__name)
    NameError: name 'self' is not defined
    

    从上面代码中可以看到,在类方法中可以访问类属性,但在类方法中访问实例属性,会出现异常。

    静态方法演示

    #! /usr/bin/env python3
    
    class People:
    
        country = 'china'
    
        def __init__(self, name):
            self.__name = name
    
        # 静态方法中即没有self 参数也不没有cls 参数
        @staticmethod
        def static_method_test1():
            print('在静态方法中访问类属性country:%s' % cls.country)
    
        @staticmethod
        def static_method_test2():
            print('在静态方法中访问实例属性__name:%s' % self.__name)
    

    使用:

    >>> p = People('小明')
    >>> p.static_method_test1()      # 在静态方法中访问类属性,出现异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/wp/to_beijing/People.py", line 14, in static_method_test1
        print('在静态方法中访问类属性country:%s' % cls.country)
    NameError: name 'cls' is not defined
    >>>
    >>> p.static_method_test2()     # 在静态方法中访问实例属性,出现异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/wp/to_beijing/People.py", line 18, in static_method_test2
        print('在静态方法中访问实例属性__name:%s' % self.__name)
    NameError: name 'self' is not defined
    

    从上面代码中可以看到,在静态方法中无论访问实例方法还是类方法,都会出现异常。

    3,专有方法

    我们之前讲到过的魔法方法,即以双下划线__开头且结尾的方法__xxx__,就是专有方法。这些方法都被Python 赋予了特殊的含义,用户可以根据需要,来实现这些方法。

    下面我们介绍一些 Python 中常见的专有方法。

    __len__ 方法

    实现该方法的类的对象,可以用len() 函数计算其长度。

    __str__ 方法

    实现该方法的类的对象,可以转化为字符串。

    __call__ 方法

    实现该方法的类的对象,可以像函数一样调用。

    __iter__ 方法

    实现该方法的类的对象,是可迭代的。

    __setitem__ 方法

    实现该方法的类的对象,可以用索引的方式进行赋值。

    __getitem__ 方法

    实现该方法的类的对象,可以用索引的方式进行访问。

    __contains__ 方法

    实现该方法的类的对象,可以进行in 运算。


    __add__ 方法

    实现该方法的类的对象,可以进行加+运算。

    __sub__ 方法

    实现该方法的类的对象,可以进行减-运算。

    __mul__ 方法

    实现该方法的类的对象,可以进行乘*运算。

    __div__ 方法

    实现该方法的类的对象,可以进行除/运算。

    __pow__ 方法

    实现该方法的类的对象,可以进行乘方运算。

    __mod__ 方法

    实现该方法的类的对象,可以进行取模运算。


    __eq__ 方法

    实现该方法的类的对象,可以进行相等==比较。

    __ne__ 方法

    实现该方法的类的对象,可以进行不等于!=比较。

    __gt__ 方法

    实现该方法的类的对象,可以进行大于>比较。

    __ge__ 方法

    实现该方法的类的对象,可以进行大于等于>=比较。

    __lt__ 方法

    实现该方法的类的对象,可以进行小于<比较。

    __le__ 方法

    实现该方法的类的对象,可以进行小于等于<=比较。

    (完。)


    推荐阅读:

    Python 简明教程 --- 15,Python 函数

    Python 简明教程 --- 16,Python 高阶函数

    Python 简明教程 --- 17,Python 模块与包

    Python 简明教程 --- 18,Python 面向对象

    Python 简明教程 --- 19,Python 类与对象


    欢迎关注作者公众号,获取更多技术干货。

    码农充电站pro

  • 相关阅读:
    30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)
    JavaScript事件流原理解析
    Java中this和super的用法和区别
    Java多态面试题案例几解题思路
    Java多态的向上转型和向下转型
    Java方法的重载和重写
    Java冒泡具体的原理,以及下标的变化
    Java中的冒泡排序和选择排序
    使用Java实现对一个数组的增删改查以及初始化
    Java中构造函数传参数在基本数据类型和引用类型之间的区别
  • 原文地址:https://www.cnblogs.com/codeshell/p/13197968.html
Copyright © 2011-2022 走看看