类的其他方法

1.函数与方法的判断

  1.1 通过打印类名的方式

class A:
    def func(self):
        pass
def func():
    pass
print(A.func)     <function A.func at 0x000001ED27190BF8>
print(func)       <function func at 0x0000028B166C2EA0>
obj = A()
print(obj.func)   <bound method A.func of <__main__.A object at 0x0000028B1689E9E8>>

  1.2 借助FunctionType,MethodType

from types import FunctionType
from types import MethodType
def func():
    pass
class A:
    def func(self):
        pass
obj = A()
print(isinstance(func,FunctionType))        # True,函数
print(isinstance(A.func,FunctionType))     # True,函数
print(isinstance(obj.func,MethodType))     # True,方法

  1.3 类中的实例方法:

      如果通过类名调用,就是FunctionType

      如果通过实力调用,就是MethodType

    类中的类方法:

      类中的类方法: 是方法MethodType

      类中的静态方法: 是函数FunctionType

  1.4 方法和函数的区别

     函数显性传参,不依赖于对象

    方法是隐性传参,要依赖对象,类

2.类的约束

  制定了一个强制的标准,强制子类要有父类规定的方法(并没有做到强制的规范,如果不继承,约束就没用)

  2.1 raise Exception(),主动报错,在父类的方法中主动抛出异常

class Payment:
     def pay(self,money):
         raise Exception('子类要定义pay方法!!!')
 class Alipay(Payment):
     def pay(self,money):
         print('使用阿里支付了%s元'% money)
 class QQpay(payment):
     def pay(self,money):
         print('使用QQ支付了%s元'% money)
class WeChatpay(self,money):
    def zhifu(self,money):
        print('使用微信支付了%s钱'% money)
def pay(self,money):            *****   统一了支付方式,归一化设计
    obj.pay(money)
obj1 = Alipay()
obj2 = WeChatpay()
obj1.pay(10)
obj2.pay(10)

  2.2 引用抽象类,接口类;子类实例化对象时没有这个方法就报错

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):    # 抽象类 接口类  规范和约束  metaclass指定的是一个元类
    @abstractmethod
    def pay(self):
        pass  # 抽象方法

class Alipay(Payment):
    def pay(self,money):
        print('使用支付宝支付了%s元'%money)
class WeChat(Payment):
    def zhifu(self,money):
        print('使用微信支付了%s元'%money)
def pay(a,money):
    a.pay(money)

ali
= Alipay() ali.pay(100) pay(ali,money)    # 归一化设计,不管是哪一个类的对象,都调用同一个函数完成相似功能
we
= Wechat() we.zhifu()      # 用的时候就会报错
pay(we,
100)

3.类的成员

  3.1类方法(使用装饰器@classmethod)

    主动接收类名,与类的静态属性相关,与对象无关的需求,需要使用类方法

    类名.类方法  对象.类方法, 传给cls的都是类空间

设置一个场景: 计算班级学生人数
class
Student: stu_num = 0 def __init__(self,name,age): self.name = name self.age = age Student.add_num() @classmethod def add_num(cls): cls.stu_num += 1 def get_num(self): return cls.stu_num ali = Student('阿狸',6) tuan = Student('团子',5) print(Student.get_num()) 结果为2

  3.2静态方法(使用装饰器@staticmethod)

    静态方法不依赖于对象和类,但是为了保持代码的一致性和整体性,可以将其设置为静态方法,是一个独立的,单纯的函数

设定一个场景,时间操作,其中有一个获取当前时间的函数
import time
class Timetest:
    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)
t = Timetest(2,10,10)
now_time = t.showTime()
print(now_time)

  3.3属性(使用装饰器@property)

    用的最多,也见的最多

写法一:

class A:
    def __init__(self)
        pass
    @property
    def AAA(self):
        print('执行的时候执行')
    @AAA.setter
    def AAA(self):
        print('修改的时候执行')
    @AAA.deleter
    def AAA(self):
        print('删除的时候执行')
f1 = A()
f1.AAA
f1.AAA = 'aaa'
del f1.AAA

写法二:

class Foo:
    def get_aa(self):
        print('')
    def set_aa(self):
        print('')
    def del_aa(self):
        print('')
    aa = property(get_aa,set_aa,del_aa)
f1 = Foo()
f1.aa
f1.aa = 'aaa'
del f1.aa

  3.4特殊的双下方法

  双下方法是解释器提供的由 __方法名__的具有特殊意义的方法,主要是python源码程序员使用,深入的研究双下方法,会更便于阅读源码.不同的双下方法有不同的触发方式

  __init__,实例化对象时,就执行__init__方法

  __len__

class A:
    def __len__(self):
        print(666)
a = A()
len(a)           # 只要len一个实例化对象,就会出发__len__方法

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))

  __hash__

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __hash__(self):
        return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))            # 随机生成一个哈希值,hash一个实例化对象就调用

  __str__

class A:
    def __str__(self):
        return '123'      return后面不能是 int 类型
a = A()
print(a)
print('%s'%a)          # 打印对象时,默认输出该方法的返回值

  __repr__

class A:
    def __repr__(self):
        return '太白'
a = A()
print(repr(a))
print('%r'%a)          # repr(对象)时,默认输出该方法的返回值

  __call__

class A:
    def __call__(self,*args,**kwargs):
        print('__call__')
a = A()
a()
A()()              # 对象+()触发执行__call__方法,或是类名()()

  __eq__

def __init__(self):
    self.a = 1
    self.b = 2
def __eq__(self,obj):
    if self.a == obj.a and self.b == obj.b
        return True
a = A()
b = B()
print(a==b)          # 比较两个实例化对象时触发

  __new__构造方法

class A:
    def __init__(self):
        self.x = 1
        print('in init')
    def __new__(cls,*args,**kwargs):
        print('in new')
        return object.__new__(A,*args,**kwargs)
a = A()
print(a.x)

  单例模式:一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例,且该实例易于被外界访问,从而可以节约系统资源,控制实例个数

class A:
    def __new__(cls,*args,**kwargs):
        if cls.a is None:
            obj = object.__new__(cls)
            cls.a = obj
        return cls.a

  __item__

class A:
    def __init__(self,name):
        self.name = name
    def __getitem__(self,item):
        print('self.__dict__[item]')
    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
a = A()
a['age'] = 18                 # 自动触发__setitem__
del a['age']                 # 触发__delitem__
a['name'] = 'alex'              # 自动触发__setitem__
print(a.__dict__)

  __enter__和__exit__: 上下文管理

class A:
    def __init__(self, text):
        self.text = text
    def __enter__(self):  # 开启上下文管理器对象时触发此方法
        self.text = self.text + '您来啦'
        return self  # 将实例化的对象返回f1
    def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
        self.text = self.text + '这就走啦'
    
with A('大爷') as f1:
    print(f1.text)
print(f1.text)

4.反射: 通过字符串对实例化对象进行相应操作

  hasattr,检测是否含有某种属性,  getattr,获取某个属性

  setattr,设置某个属性,      delattr,删除某个属性

  01. 对对象进行反射

class A:
    def __init__(self,name,age):
        self.name = name
        self.age = age
obj = A('小胖',18)
print(hasattr(obj, 'name'))
print(getattr(obj, 'age'))
setattr(obj,'sex','')
print(obj.__dict__)        # {'name':'小胖','age':18,'sex':'男'}
delattr(obj,'age')
print(obj.__dict__)        # {'name':'小胖','sex':'男'}

  02. 对类的反射

class A:
    country = '中国'
    def __init__(self):
        self.name = '小胖'
    def func(self):
        return 'func'
    @staticmethod
    def bar():
        return 'bar'
print(getattr(A,'country'))      # 中国
print(getattr(A,'func'))   方法名内存# <function A.func at 0x000002BE2ABA0C80>
print(getattr(A,'bar'))    # <function A.bar at 0X000002BE2ABD8048>

  03. 当前模块的反射

import sys
def foo():
    print('in foo')
def func():
    print('in func')

module = sys.modules[__name__]
print(hasattr(module,'foo'))        # True
getattr(module,'func')            # in func

  04. 其他模块的反射

import 另一个模块名
print(hasattr(模块名, 方法名或属性名))
foo = getattr(模块名, 属性名)
print(foo)                              属性值
ret = getattr(模块名,方法名)
ret()                     # 调用另一个模块的方法

5.isinstance和issubclass

  isinstance: 判断对象是否为类的实例化对象

class A:
    pass
class B(A):
    pass
obj = B()
print(isinstance(obj,B))

  issubclass: 判断此类是否为另一个类的派生类

class A:
    pass
class B(A):
    pass
class C(B):
    pass
print(issubclass(B,A))
print(issubclass(C,A))

猜你喜欢

转载自www.cnblogs.com/py8318/p/10353601.html