zoukankan      html  css  js  c++  java
  • 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

     

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

  • 相关阅读:
    【Nginx】ngx_event_core_module模块
    ELMAH--Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components 77 out of 90 rated th
    nyist oj 214 单调递增子序列(二) (动态规划经典)
    java 入门书籍(java7)
    ARCGIS将WGS84坐标投影到高斯平面
    【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
    【springboot】【socket】spring boot整合socket,实现服务器端两种消息推送
    【linux】linux修改open file 大小
    【docker】docker限制日志文件大小的方法+查看日志文件的方法
    【docker】docker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志
  • 原文地址:https://www.cnblogs.com/lcysen/p/6087283.html
Copyright © 2011-2022 走看看