文章目录

  • 类成员
  • 一、 成员分类
  • 二、 私有成员和公有成员
  • 1、 组成
  • 2、 区别
  • 三、 其他成员
  • 1、 实例方法
  • 2、 类方法
  • 3、 双下方法
  • 4、 类方法实例
  • 4、 静态方法实例
  • 5、 属性实例
  • 四、 类约束


类成员

一、 成员分类

类大致可以分为两大部分

  1. 静态属性
  2. 动态方法
class A:  # 类对象
    # 静态属性部分
    name, age = "Make", 12  # 静态属性,类属性,在__init__外部定义
    __gender = "boy"  # 私有静态属性
    
    # 动态方法部分
    def __init__(self, name, age):  # 双下划线方法(内置方法)
        self.name = name  # 对象属性,实例属性,在__init__内部定义
        self.__age = age  # 私有对象属性
        
    def __func(self):  # 私有方法
        pass
    
    def func(self):  # 普通方法,实例方法,调用了实例属性
        pass
    
    @classmethod
    def classfunc(cls)  # 类方法,只访问类变量
    	pass
    
    @staticmethod
    def staticfunc()  # 静态方法,即不能访问类变量,也不能访问成员变量
    	pass
    
    @property
    def propfunc(self):  # 属性
        pass

if __name__ == "__main__":
    stu1 = A("lihua", 20)  # 通过类创建的对象称为实例对象
    stu1.func()
    stu2 = Car("dak", 40)
    stu2.func()
    A.classfunc()  # 调用类方法
    A.staticfunc()  # 调用静态方法

二、 私有成员和公有成员

1、 组成

对于每个类的成员而言

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

2、 区别

静态属性

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

对象属性

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

方法

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

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

非要访问私有成员的话,可以通过 对象._类__属性名

三、 其他成员

其他成员就是类方法

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

1、 实例方法

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

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

2、 类方法

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

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

3、 双下方法

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

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

4、 类方法实例

应用场景

  • 类中有些方法是不需要对象参与
class A:
    name = "dogfa"
    index = 0

    @classmethod
    def func(cls):
        return cls.name + str(cls.index)

print(A.func())
  • 对类中的静态变量进行改变,要用类方法
class A:
    name = "dogfa"
    index = 0

    @classmethod
    def func(cls, name):
        cls.name = name
        return cls.name

print(A.func("oldniu"))
  • 继承中,父类得到子类的类空间,然后可以对子类为所欲为
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'}

4、 静态方法实例

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

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

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

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

5、 属性实例

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

什么是特性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)