python面向对象简单整理

1. 面向对象三大特性

  • 封装

    • 归类,将函数放置到一个类中
    • 打包, 将数据打包到一个对象中,限制范围
  • 继承

    • 多个类有相似功能时
  • 多态

    • python原生支持多态,崇尚鸭子模型,由于python函数传参时,无需指定类型
def func(arg):  # arg可以接受多种类型,只需要其中有send方法即可(实现了其他语言的接口功能)
  arg.send()

2. 类成员

  • 1.类的成员
# 定义一个基类
class Base(object):

    def func(self):
        print(123) 


# 子类 继承 基类
class Foo(Base):
    country = "中国"  # 类变量/静态字段
    

    def __init__(self,name):
        self.name = name  # 实例变量/字段
        self.__salary = 2000  # 实例化的外部不能访问
    
    # 实力方法
    def func(self):
        print(Foo.country)  # 推荐是用类名+变量名
        print(self.country) 
        
        # 调用类的成员
        Base.func(self)
        super.func(self)  # 推荐使用
        
    # 静态方法  建议是用类调用 Foo.salary()
    # 如果方法中无需使用对象中封装的自己的变量
    @staticmethod
    def salary(self):  # 私有变量  外部使用函数访问
        return self.__salary
        
    
    # 类方法
    # 调用 Foo.show(1,2)
    # 什么时候写: 如果该方法中使用了当前类的方法或者变量的时候写类方法  
    @classmethod
    def show(cls,x1,x2):
        print("类方法",cls.salary())
     
    # 私有实例方法   
    def __display(self,arg):
        print(arg)
    
    # 私有静态方法 
    @staticmethod
    def __display1(arg):
        print(arg)
    
    # 私有类方法 
    @classmethod
    def __display2(cls,arg):
        print(arg)
    
    # 方法包装访问私有方法
    def func(self):
        self.__display("123")
        Foo.__display1(456)
        Foo.__display2(789)
    
    # 属性  无法加参数
    # 使用  obj.start  不用加括号, 有返回值
    # 共有私有 属性  __start
    @property   
    def start(self):
        return 1
        
   
Foo.country
obj = Foo("Jeecy")  # Foo类的对象/实例

  • 分为三类

    • 实例变量(字段)
    • 类变量(静态字段)
    • 私有变量
  • 方法

    • 实例方法
    • 静态方法 @staticmethod
    • 类方法 @classmethod
    • 私有方法: 内部才能访问
  • 静态方法和类方法和实力方法的区别?

    • 定义不一样 装饰器一不一样
    • 调用不一样 obj.func() cls.func
    • 类方法 为了不想写当前类名,使用类方法 cls
  • 属性: 方法构造出来的

    • 使用 @property 修饰
    • 无法加参数
    • 使用 obj.start 不用加括号, 有返回值
    • 共有私有 属性 __start
  • 主动调用其它类成员的方法

        Base.func(self)
        super.func(self)  # 推荐使用
    

类的内置魔术方法


class Foo(object):
    # 在类生成之前自动调用的方法,多用于单例模式
    def __new__(cls, *args, **kwargs):
        
        return object.__new__(cls)  # 创建一个当前类的对象(内部时空的)
    
  # 类的构造方法, 在类实例化成对象的时候自动执行的方法
    def __init__(self,name,age):
        self.name = name
        self.age = age
    
    # obj()  对象加()  自动调用 __call__方法
    def __call__(self, *args, **kwargs):
        # 打印接受值
        print(*args, **kwargs)
        # 返回一个值
        return 6
    
    
    # obj["yu"]  对象加['item'] 调用  __getItem__方法
    def __getitem__(self, item):
        # 打印接受值
        print(item)
        # 返回值
        return 666
    
    
    # obj["key"] = value 调用 __setItem__ 方法  无返回值
    def __setitem__(self, key, value):
        print(key,value)
        
    # del obj["key"]  调用 __delitem__ 方法  没有返回值
    def __delitem__(self, key):
        print(key)
        
    
    # obj + obj   
    def __add__(self, other):
        print(self.age + object.age)
        
        return 888
        
    
    # with obj as f:  就要执行  如果有返回值就  as f 接受
    def __enter__(self):
        print('111')
        return 6
    
    # with 执行完内部代码后要执行的内容
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('222')
        
    # 直接打印这个类或者对象的时候显示的内容
    def __str__(self):
        return self.name
        
    # 类的注释
    # 无需定义
    #def __doc__(self):
        #pass
    
    # 获取对象封装的数据
    # 无需定义  
    # def __dict__(self):
        # pass
    
    # 使对象便可的迭代  返回一个迭代器
    def __iter__(self):
        return iter(11,22,33,44,55,66)
        





  • 特殊成员
    • def __init__(self)

    • def __new__(cls)

    • obj() 对象加括号会调用 下面call方法
      def __call__(self,*args,**kwargs)

    • obj[] 自动执行 __gitItem__(self,item)

def __getItem(self,item):
  print(item)
  return 6
  • issubclass
    issubclass(Foo,Base) Foo 是不是 Base的子子孙孙类
  • type
    from types import MethodType,FunctionType
    type(obj) == Foo obj是不是 Foo的实例
  • isinstance
    isinstance(obj,Foo) 对象 是不是 类/基类的 实例

使用类写一个分页

class Pagenation(object):
    def __init__(self, data_list, page, per_page_num=10):
        '''
        初始化
        :param data_list: 数据源
        :param page: 当前要查看的页码数
        :param per_page_num: 每页要显示的页码数
        '''
        self.data_list = data_list
        self.page = page
        self.per_page_num = per_page_num

    @property
    def start(self):
        '''
        起始条数索引
        :return:
        '''
        return (self.page - 1) * self.per_page_num

    @property
    def end(self):
        '''
        结束条数索引
        :return:
        '''
        return self.page * self.per_page_num

    def show(self):
        page_data_list = data_list[self.start:self.end]

        for item in page_data_list:
            print(item)


# 数据源
data_list = []

for i in range(1, 901):
    data_list.append(f"Jack-{i}")

while True:
    page = int(input("请输入要查看的页码数:"))
    obj = Pagenation(data_list, page)  # 实例化一个分页
    obj.show()  # 展示

方法 和 函数的区分

  • 类 -> 方法
  • 函数 - 函数

反射

hasattr(handler,val)  # 有没有这个属性

f = getattr(handler,val)  # 根据字符串为参数,去模块/类/对象中寻找与之同名的成员


class Foo(object):
    pass

setattr(Foo,'x2',"sdfasdfa")  # 添加变量

setattr(Foo,"xx",lambda x:x+1) # 添加方法

a = getattr(Foo,"xx")
print(a(2))

判断一个 arg() arg是否能被调用

callable(arg) 返回 True False

类的约束

class BaseMessage(object):
    
    def send(self):
        raise NotImplementedError("send() 必须被重写")
        
# 约束  派生类必须重写父类方法 有几个参数  子类也需要有几个参数
  • 抽象类 抽象方法
from abc import ABCMeta,abstractmethod

class Base(metaclass=ABCMeta):
  
    @abstractmethod
    def f2(self):  # 抽象方法
        pass
  • 抽象类 和抽象方法 子类必须重写 来实现这个方法
  • 接口: 易中数据类型 用于约束派生类中必须实现指定的方法
    python中不存在,java和c#中是存在的
    python中使用抽象类和抽象方法:编写麻烦 或者 认为的主动抛出异常
    抛出的异常是 raise NotImplementedError("send() 必须被重写")

自定义异常


import os
class ExistsError(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message

class KeyInvalidError(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message

def func(path,prev):
    """
    去 path路径中的文件中 找到前缀为prev的一行数据,获取数据并返回给调用者
    1000 成功
    1001 文件不存在
    1002 关键字为空
    1003 未知错误
    :param path: 文件路径
    :param prev: 关键字
    :return: response
    """
    response = {
        "code": 1000,
        "data":None
    }
    try:
        if not os.path.exists(path):
            raise ExistsError(1001,"文件不存在")
        if not prev:
            raise KeyInvalidError(1002,"关键字为空")

    except ExistsError as e:
        response["code"] = e.code
        response["data"] = e.message
    except KeyInvalidError as e:
        response["code"] = e.code
        response["data"] = e.message
    except Exception as e:
        response["code"] = 1003
        response["data"] = "未知错误"
    return response

你可能感兴趣的:(python面向对象简单整理)