• python之路——面向对象(进阶篇)


    面向对象进阶:类成员、类成员的修饰符、类的特殊成员

    类成员

    类成员分为三大类:字段、方法、属性

    一、字段

    • 静态字段 (属于类)
    • 普通字段(属于对象)
     1 class City:
     2     # 静态字段
     3     country = "中国"
     4 
     5     def  __init__(self,city_name):
     6         # 普通字段
     7         self.city_name = city_name
     8 
     9     def show(self):
    10         print(self.city_name)
    11 
    12 
    13 obj1 = City("Harbin")
    14 obj2 = City("Shanghai")
    15 # 普通字段对象来访问
    16 print(obj1.city_name,obj2.city_name)
    17 # 静态字段通过类名访问
    18 print(City.country)  
    字段

    内存中分布:

    1. 静态字段在内存中只保存一份
    2. 普通字段在每个对象中都要保存一份

    静态字段定义及应用:随着这个程序的执行产生,随着程序的结束而消失,这样和程序‘共存亡’的字段,我们就叫它静态字段。它就像是一个全局变量,不属于任何一个对象,我们可以直接使用类来调用,也可以在对象使用方法的时候使用它。它是对象共享的变量,存在类的内存里。

    特殊:对象也可以访问静态字段。静态字段在代码加载时已经创建。

    遵循规则:普通字段只能对象访问;静态字段用类访问。(万不得已用对象访问)

    二、方法

    • 静态方法:由调用;无默认参数;
    • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
     1 class Province:
     2 
     3     country = "China"
     4     def __init__(self,name):
     5         self.name =  name
     6 
     7     # 普通方法 由对象调用。
     8     def show(self):
     9         print(self.name)
    10 
    11     # 静态方法 ,无self参数;方法前边加上关键字@staticmethod 由类调用
    12     @staticmethod
    13     def display(a,b,c):
    14         print(a,b,c)
    15 
    16     # 类方法(相当于静态方法特殊形式),至少要有一个cls参数。由类调用
    17     @classmethod
    18     def listen(cls,b):
    19         '''
    20         cls:类名
    21         '''
    22         print(cls.country,b)
    23 
    24 obj = Province("黑龙江")
    25 obj.show() # 普通方法由对象调用
    26 Province.display(1,2,3) # 静态方法由类调用执行
    27 Province.listen(2) # cls是python自动传递
    方法

    三、属性

    • 属性的基本使用
     1 class Page:
     2 
     3     def __init__(self,all_counts):
     4         self.all_counts = all_counts
     5 
     6     # 属性: 分页
     7     @property
     8     def divpages(self):
     9         a,b = divmod(self.all_counts,10)
    10         if b == 0:
    11             return a
    12         else:
    13             return a+1
    14 
    15 
    16 p = Page(101)
    17 ret = p.divpages# 调用属性 直接返回
    18 print(ret)

    属性的定义和调用:

    • 定义时,在普通方法的基础上添加 @property 装饰器;
    • 定义时,属性仅有一个self参数
    • 调用时,无需括号
                 属性:p.divpages

    Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回

    注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象

            属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。

     1 class Page:
     2 
     3     def __init__(self,all_counts):
     4         self.all_counts = all_counts
     5 
     6     # 属性: 分页
     7     @property
     8     def divpages(self):
     9         a,b = divmod(self.all_counts,10)
    10         if b == 0:
    11             return a
    12         else:
    13             return a+1
    14     # 设置属性:支持赋值操作
    15     @divpages.setter
    16     def divpages(self,value):
    17         self.all_counts = value
    18     # 删除
    19     @divpages.deleter
    20     def divpages(self):
    21         print("del property")
    22 p = Page(101)
    23 p.divpages = 111 #自动执行 @divpages .setter 修饰的 divpages 方法,并将  123 赋值给方法的参数
    24 ret = p.divpages # 自动执行 @property 修饰的 divpages方法,并获取方法的返回值
    25 del p.divpages  # 自动执行 @divpages.deleter 修饰的 divpages方法
    26 print(ret)

    属性操作:不同属性调用形式,触发不同装饰器的方法,见下图。

     

    • 属性另一种表达方式 
    class Page:
    
        def __init__(self,count):
            self.count = count
    
         
        def f1(self):
            return 123
        
        def f2(self):
            print("fset:赋值")
    
        def f3(self):
            print("fdel:删除")
    
        foo = property(fget=f1,fset=f2,fdel=f3)
    
    p = Page(100)
    ret = p.foo # 自动回找到fool,会找到fget对应函数f1并执行,并将返回值
    p.foo =113 #会找到fset对应函数f2并执行
    del p.foo # 会找到fdel并执行f3

    类成员修饰符

    • 公有:在类内和类外均可以访问
    • 私有:仅在类的内部可以访问;私有成员命名时,前两个字符是下划线
    1. 公有字段和私有字段
     1 class Person:
     2     # 私有 静态字段
     3     __school = "北大"
     4     def __init__(self,name,sex):
     5         # 普通字段,公有,name ;私有 sex 
     6         self.name = name
     7         self.__sex = sex
     8     
     9     # 均可在类内调用
    10     def f1(self):
    11         print(self.name)    
    12         print(self__sex)
    13 
    14     def f2(self):
    15         print(Person.__school)
    16 
    17 class ChianPerson(Person):
    18     def f2(self):
    19         print(self.__sex)
    20     
    21 obj = Person("lcy","man")
    22 print(obj.name) # 类外访问公有普通字段
    23 # print(obj.__sex) # 无法访问 报错 no attribute 
    24 #print(Person.__school) # 无法访问
    25 obj.f3() # 打印 "北大"
    26 # ----- 继承,派生类不能访问基类私有的普通字段-------
    27 obj2 = ChinaPerson("alex","female")
    28 #obj2.f2() # 执行 失败,只有Person类内方法可以访问
    29 obj2.f1() # 可以执行f1是Person类中的方法

      2. 公有方法和私有方法

    (略)

    这里公有方法和私有方法与上边字段访问限制是一样的。私有方法命名同私有字段命名相同。只要在函数名前加两个下划线,就表示私有方法。

     类的特殊成员

    • __init__:构造方法
    • __del__:析构方法
    • __doc__:注释类
    • __module__:对象所在模块
    • __class__:对象类名
    • __call__: obj() 或类名()触发执行
    • __str__:print(obj)自动调用
    • 其他:__add__
     1 class Person:
     2     '''
     3     这是一个人类
     4     '''
     5     def __init__(self,name):
     6         self.name = name
     7 
     8     def __del__(self):
     9         print("这是析构函数一般不自定义,python有自己的回收机制")
    10 
    11     def __call__(self, *args, **kwargs):
    12         print("call")
    13 
    14     def __str__(self):
    15         return  ("__str__:%s"%self.name)
    16 
    17     def __add__(self, other):
    18         print(self.name,other.name)
    19         
    20 
    21 
    22 # 创建对象,自动调用__init__
    23 obj_p1 = Person("lcy")#
    24 obj_p2 = Person("alex")
    25 print(obj_p1.__doc__)
    26 print(obj_p1.__module__)
    27 print(obj_p1.__class__)
    28 # 自动调用 __call__
    29 obj_p1()
    30 #Person("lcy")() 同 obj_p1()
    31 # 触发__str__方法
    32 print(obj_p1)
    33 res = str(obj_p1)
    34 print(res)
    35 # 会触发 __add__ /同理会有其他的方法,加减乘除。。。
    36 obj_p1+obj_p2
    37 # 程序会自动调用__del__析构函数,对象在回收机制之前,这里会调用两次,因为创建了两次
    • __dict__:重点 (默认已经存在类或者对象中)

    获取类成员:静态字段,方法。

     1 class Game:
     2 
     3     Game_name = "SIM3"
     4 
     5     def  __init__(self):
     6         pass
     7 
     8     def show(self):
     9         pass
    10 
    11 print(Game.__dict__)
    12 '''
    13 {'__init__': <function Game.__init__ at 0x00503E88>, 
    14 'show': <function Game.show at 0x00503DF8>, 
    15 '__weakref__': <attribute '__weakref__' of 'Game' objects>,
    16 '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Game' objects>,
    17 'Game_name': 'SIM3', '__doc__': None}
    18 '''

    对象:获取对象的字段

     1 class Game:
     2 
     3     Game_name = "SIM3"
     4 
     5     def  __init__(self,level,money):
     6         self.level = level
     7         self.money = money
     8 
     9     def show(self):
    10         pass
    11 obj = Game(12,199)
    12 print(obj.__dict__)
    13 '''
    14 {'money': 199, 'level': 12}
    15 '''
    • __getitem__、__setitem__、__delitem__

    对象用于索引,如字典相关操作。获取、设置以及删除操作

     1 class Foo:
     2 
     3     def __getitem__(self, item):
     4         print(item)
     5 
     6     def  __setitem__(self, key, value):
     7         print(key,value)
     8 
     9     def __delitem__(self, key):
    10         print(key)
    11 
    12 obj = Foo()
    13 obj["k1"] # 触发 __getitem__
    14 obj[3]   #触发 __getitem__
    15 obj[2] = 234 # 触发__setitme
    16 del obj[3] # 触发__delitem

    支持对象切片操作。(python3 用触发上边的方法来实现)

     1 class Foo:
     2 
     3     def __getitem__(self, item):
     4         print(type(item))
     5         print(item.start)
     6         print(item.stop)
     7         print(item.step)
     8 
     9     def  __setitem__(self, key, value):
    10         print(type(key))
    11         print(key.start,key.stop,key.step,value)
    12 
    13     def __delitem__(self, key):
    14         print(type(key))
    15         print(key.start,key.stop,key.step)
    16 
    17 obj = Foo()
    18 obj[1:3:2] # 触发 __getitem__
    19 obj[1:3:2] = [11,22,44]   #触发 __setitem__
    20 del obj[1:3:2] # 触发__delitem__
    输出:

    <class 'slice'>
    1
    3
    2
    <class 'slice'>
    1 3 2 [11, 22, 44]
    <class 'slice'>
    1 3 2

     

    (待续,天冷,打字都动手啊)

  • 相关阅读:
    POJ 3660 Cow Contest
    HDOJ 2093 sscanf的使用,字符串对齐,快排
    HDOJ 2091 空格的特殊输入输出格式
    COJ 1081: 集训队分组
    HDOJ 2948 错排公式
    POJ 1936 All in All
    POJ 1035 Spell checker
    HDOJ 2094 set和map的使用
    HDOJ 2036 多边形的面积
    HDOJ 1166 敌兵布阵
  • 原文地址:https://www.cnblogs.com/lcysen/p/6087283.html
Copyright © 2020-2023  润新知