Python深入类和对象

1. 抽象基类

Python的鸭子类型无法判断对象类型,为了有判断类型的手段Python中提供了抽象基类,使用装饰器 @abc.abstractmethod和abc模块实现抽象基类的创建
抽象基类的创建和分析:

class CacheBase(metaclass=abc.ABCMeta):  #抽象基类的定义
    @abc.abstractmethod # 抽象方法的定义
    def get(self, key):
      pass

    @abc.abstractmethod
    def set(self, key, value):
        pass


class MyCacheBase(CacheBase): # 继承CacheBase
     def set(self, key, value): #重写抽象方法 不重写会出现异常
         return key+" "+value

     def get(self, key):
         return  key
if __name__ == '__main__':
    readis_List = MyCacheBase()
    b= readis_List.set("boby", "value")
    a= readis_List.get("boby")
    print(b) #输出 boby value
    print(a) #输出 boby 

总结:实现抽象基类的抽象方法才能实现继承,抽象基类很好的把类单独的区分开了,要使用特定的类,就必须实现相应的方法,这就是抽象基类。

2. isinstance和type的区分

两者都可以判断实例的类型,下面分析二者的区别:

class A:
    pass
class B(A):
    pass
if __name__ == '__main__':
    a = B()
    print(isinstance(a, A)) #输出 True    
    print(isinstance(a, B)) #输出 True   
    print(type(a) is B) # 输出 True
    print(type(a) is A) #输出 False

分析上述代码 :A是B的基类,B是A的子类,type只能判断a和B是同类型,isinstance函数可以判断a和B以及基类都是同类型对象,isinstance内部的判断比type更加全面

3. 魔法函数

Python内部的魔法函数比较多,这里介绍几个入门的:

class Person:
	def ask(name="名字"): #普通方法
    	print(name)
class Commany:
    def __init__(self, name): #构造函数
        self.Name = name
    def __getitem__(self, item):  # __的方法称为魔法函数  getitem代表对象可迭代 并不是迭代函数
        return self.Name[item]  # item是索引
    def __len__(self):   #计算长度
        return len(self.Name)
if __name__ == '__main__':
    b = Commany(["tome", "Jack", "Li","MM"]) #调用构造
    c = b.Name
    for a in b:  # python for的自动语法 存在 getitem可迭代 反之无法执行for循环
        print(a) # 输出tome Jack  Li  MM
print(len(b))   #输出4  获取类中赋值列表的长度 因为存在len魔法函数可以执行 反之报错      

总结:魔法函数定义在类中,无需调用,在执行某些需求时会向类中查找。

4. 类方法、静态方法、和实例方法

关于Python的方法类型直接看代码:

# 一段根据输入的YYYY-MM-SS 给用户反馈YYYY/MM/SS 的日期代码
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    def __str__(self):
        return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day)

    @staticmethod  #静态方法
    def sta_show(str_date):
        try:
            year, month, day = tuple(str_date.split("-")) # 分割日期符号
        except Exception as e:
            print("格式错误 False") # 判断输入是否合法
        if int(year) > 0 and int(month) < 12 and int(day) < 31:
            return True
            
    @classmethod #类方法
    def cla_show(cls, str_date):  # 传入类变量
         year, month, day = tuple(str_date.split("-")) 
         return Date(int(year), int(month), int(day))
         
class Demo:
    def tomorrow(self): # 实例方法
        print("这是日期")
        
if __name__ == '__main__':
    str_date = input("输入日期 格式为YYYY-MM-SS:")
    new_day = Date.sta_show(str_date) #调用静态方法
    new_day1 = Date.cla_show(str_date) #调用类方法
    d = Demo() #创建实例
    d.tomorrow() #调用实例方法
    print(new_day)
    print(new_day1)

5. 数据封装即私有属性

Python中的"private"。

class User:
    def __init__(self, boy):
        self.__boy = boy #这里的boy就是私有的属性
    def get_boy(self):
        return  self.__boy
if __name__ == '__main__':
    user = User("Jack")
    #user.boy是行不通的需要使用get方法
    b = user.get_boy()
    print(b) # 输出 Jack
    print(user._User__boy) #不存在所谓的绝对私有 java中的反射机制也能无视一切 但是python就有些随意了

6. 自醒机制

在Python的每一个类(类也是对象)中存在一串内部结构,在代码中展示:

class Person:
    Tname = "user"
class Student(Person):
    def __init__(self, name):
        self.name = name
if __name__ == '__main__':
    user = Student("Jack") #给name赋值Jack
    print(user.Tname) # 输出 user 
    print(user.__dict__) # dict是 python 的字典类型 输出 {'name': 'Jack'}
    user.__dict__["name"] = "MaLi" # 直接赋值
    print(user.__dict__["name"])  # 输出 MaLi
#下面3句的输出结果分别在结尾的 1 ,2 ,3
    print("1",Person.__dict__) 
    print("user", dir(user)) #dir 输出全部的内部结构
    print("Person", dir(Person))    
   


#1. {'__module__': '__main__', 'Tname': 'user', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} 

#2. user ['Tname', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']

#3. Person ['Tname', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    

总结:这里的输出结果就是Python中的的内部Key的结构

7. 父类Super函数

class A:
    def __init__(self):
        print("A")

class B(A):
    def __init__(self):
        print("B")
        super().__init__()

class C(A):
    def __init__(self):
        print("C")
        super().__init__()

class D(B, C):
    def __init__(self):
        print("D")
        super(D, self).__init__()
if __name__ == '__main__':
  	d = D()
    print(D.__mro__) # 打印RMO算法的寻址路径
#输出结果
#D
#B
#C
#A
#(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

总结:父类并不是调用父类的构造,而是通过MRO的路径去调用相应的方法

8. 上下文管理器协议

#上下文管理器 with语句
class Sample():
    def __enter__(self):
        # 获取资源
        print("跑起来了")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        #释放资源
        print("exit")
    def do_something(self):
        print("doing something")

if __name__ == '__main__':
    with Sample() as sample: #  sample 是 Sample类的对象
        sample.do_something() #调用方法 默认去执行 enter 和 exit


简化操作:

#contextlib 简化管理器
import contextlib
@contextlib.contextmanager  #装饰器 变成上下文管理器
def file_open(file_name):
    print("file_start")
    yield{}  # 定义生成器
    print("file end")             

if __name__ == '__main__':
    with file_open("box") as f:
        print("执行中")
#输出结果
#file_start
#执行中
#file end        

总结:上下文管理器协议可以方便在开头获取资源在结尾释放资源,自动向类中查找enter 和 exit 魔法函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

让我在看看

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值