• Python类的成员


    Python类的成员

    一、细分类的组成成员

    类大致分为两大部分:

    1. 静态属性
    2. 动态方法
    class A:
    	# 静态属性部分
    	name = "dogfa"
    	age = 18
    	
    	# 动态方法部分
    	def __init__(self, name, age):
    		self.name = name
    		self.age = age
    

    每个区域详细划分又可以分为:

    class A:
        name = "dogfa"  # 静态属性
        __age = 18 	    # 私有静态属性
    
        def __init__(self, name, gender):  # 双下方法(内置方法)
            self.name = name               # 对象属性
            self.__gender = gender         # 私有对象属性
    
        def __func(self):       # 私有方法
            pass
    
        def func(self):         # 普通方法
            pass
    
        @classmethod
        def classfunc(cls):     # 类方法
            pass
    
        @staticmethod
        def staticfunc():       # 静态方法
            pass
    
        @property
        def prop(self):         # 属性
            pass
    
    

    二、类的私有成员

    对于每一个类的成员而言都有两种形式:

    • 公有成员,在任何地方都能访问
    • 私有成员,只有在类的内部才能方法

    私有成员和公有成员的访问限制不同

    静态属性

    • 公有静态属性:类可以访问;类内部可以访问;派生类中可以访问
    • 私有静态属性:仅类内部可以访问;

    对象属性

    • 公有对象属性:对象可以访问;类内部可以访问;派生类中可以访问
    • 私有对象属性:仅类内部可以访问;

    方法:

    • 公有方法:对象可以访问;类内部可以访问;派生类中可以访问
    • 私有方法:仅类内部可以访问;

    总结:对于这些私有成员来说,他们只能在类的内部使用,不能再类的外部以及派生类中使用。

    tips:非要访问私有成员的话,可以通过 对象._类__属性名,但是绝对不允许!!

    为什么可以通过._类__私有成员名访问呢?因为类在创建时,如果遇到了私有成员它会将其保存在内存时自动在前面加上_类名。

    三、类的其它成员

    这里的其他成员主要就是类方法:

    方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

    实例方法

    ​ 定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);

    ​ 调用:只能由实例对象调用。

    类方法

    ​ 定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);

    ​ 调用:实例对象和类对象都可以调用。

    静态方法

    ​ 定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;

    ​ 调用:实例对象和类对象都可以调用。

    双下方法

     定义:双下方法是特殊方法,他是解释器提供的由双下划线加方法名加双下划线 __方法名__的具有特殊意义的方法,比如__init__

     调用:不同的双下方法有不同的触发方式,就好比盗墓时触发的机关一样,不知不觉就触发了双下方法,例如:__init__

    1. 类方法

      应用场景:

      1. 类中有些方法是不需要对象参与

        class A:
            name = "dogfa"
            index = 0
        
            @classmethod
            def func(cls):
                return cls.name + str(cls.index)
        
        print(A.func())
        
      2. 对类中的静态变量进行改变,要用类方法

        class A:
            name = "dogfa"
            index = 0
        
            @classmethod
            def func(cls, name):
                cls.name = name
                return cls.name
        
        print(A.func("oldniu"))
        
      3. 继承中,父类得到子类的类空间,然后可以对子类为所欲为

        class A:
            name = "dogfa"
            index = 0
        
            @classmethod
            def func(cls):
                print(cls)  # 获取B类的类空间(<class '__main__.B'>)
                cls.name = "djb"    # 给B类添加静态属性
        
        class B(A):
            pass
        
        B.func()
        print(B)	# <class '__main__.B'>
        print(B.__dict__)	# {'__module__': '__main__', '__doc__': None, name': 'djb'}
        
    2. 静态方法

      静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

      import time
      
      class TimeTest(object):
          def __init__(self, hour, minute, second):
              self.hour = hour
              self.minute = minute
              self.second = second
      
          @staticmethod
          def showTime():
              return time.strftime("%H:%M:%S", time.localtime())
      
      print(TimeTest.showTime())	# 12:07:02
      t = TimeTest(2, 10, 10)
      nowTime = t.showTime()
      print(nowTime)			   # 12:07:02
      

      如上,使用了静态方法(函数),然而方法体中并没使用(也不能使用)类或实例的属性(或方法)。若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。

      其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。

    3. 属性

      属性 : 将一个方法伪装成一个 属性,在代码的级别上没有本质的提升,但是让其看起来跟合理。

      什么是特性property

      property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

      为什么要用property

      将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

      class Goods:
      
          def __init__(self, original_price, discount):
              self.original_price = original_price
              self.discount = discount
      
          @property
          def price(self):
              new_price = float(self.original_price) * float(self.discount)
              return new_price
      
          # 修改原价
          @price.setter
          def price(self, value):
              if isinstance(value, int):
                  self.original_price = value
              else:
                  raise TypeError("{0} must be in int".format(value))
      
          # 删除原价
          @price.deleter
          def price(self):
              del self.original_price
      
      
      good = Goods(100, 0.8)
      # 获取商品价格
      print(good.price)		# 80.0
      
      # 修改商品价格
      good.price = 89
      print(good.price)		# 71.2
      

    四、类的约束

    抽象类:抽象类是一个介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。

    Python中没有接口类这种东西。

    引入抽象类的概念对类进行约束:

    from abc import ABCMeta, abstractmethod
    
    class Payment(metaclass=ABCMeta):    # 抽象类 规范和约束  metaclass指定的是一个元类
        @abstractmethod
        def pay(self): pass     # 抽象方法
    
    class WeChatPay(Payment):
        def pay(self, money):
            print("使用微信支付了{0}元".format(money))
    
    class AliPay(Payment):
        def pay(self, money):
            print("使用支付宝支付了{0}元".format(money))
    
    class JdPay(Payment):
        pass
        # def pay(self, money):
            # print("使用京东支付了{0}元".format(money))
    
    def pay(obj, money):
        obj.pay(money)
    
    
    ali = AliPay()
    wechat = WeChatPay()    # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能
    jd = JdPay()    # JdPay没有实现父类中的抽象类pay方法,在实例化对象时会报错
    
    pay(ali, 300)
    pay(wechat, 500)
    
  • 相关阅读:
    asp.net core启动源码以及监听,到处理请求响应的过程
    HTTP缓存
    【SpringData&JPA从入门到精通】02JPA API
    关于取地址&和解引用*的小问题
    多态性
    ASP.NET Core WebApi返回结果统一包装实践
    后端思维之数据库性能优化方案
    【项目】项目194
    lambda 表达式
    在APICloud开发平台使用友盟统计功能教程
  • 原文地址:https://www.cnblogs.com/wangyueping/p/11108437.html
Copyright © 2020-2023  润新知