Python_学习之面向对象

一、定义
类:具有相同属性和能力的一类事物

对象:类的具体表现

语法:

# 构建
class LearnPython(object):
    """
    类名必须首字母大写,驼峰体
    """

    country = "China"  # 静态变量

    def __init__(self, name, location):  # 动态方法
        self.name = name
        self.location = location

    def read(self):
        pass

# 类
# 查看类拥有的所有属性与方法
print(LearnPython.__dict__)

# {'__module__': '__main__',
 '__doc__': '\n    类名必须首字母大写,驼峰体\n    ',
 'country': 'China',
 '__init__': <function LearnPython.__init__ at 0x000001E81E75E8C8>,
 'read': <function LearnPython.read at 0x000001E81E75E510>,
 '__dict__': <attribute '__dict__' of 'LearnPython' objects>,
 '__weakref__': <attribute '__weakref__' of 'LearnPython' objects>}

# 实例化
obj = LearnPython("Elvin", "北京")
# 查看实例所有的属性
print(obj.__dict__)  # {'name': 'Elvin', 'location': '北京'}
# 查看实例拥有的方法【能力】
print(obj.read())   # Elvin在北京看故宫
# 对属性值的更改
obj.name = "LiLei"
del obj.name
print(obj.__dict__)

二、实例化及创建对象的过程

一旦执行ClassName()类实例化动作,自动执行类中的new()方法,当前类中没有的则去基类object中执行new(cls,*args,**kwargs),创建一个对象空间,返回给ClassName(),

然后执行init方法,将对象空间传给self,init方法为这个对象空间初始化封装属性,

最后将封装好的属性返回给ClassName()

三、类与对象的小结

类名:
1、类名查看类中所有的变量(字段),方法(函数):类名.__dict__
2、类名对静态变量进行操作
  方法一、类名.__dict__["变量名"] 只能查,报错不能增删改 **不用**
  方法二、类名.变量名 可增删改查 *****常用******  
3、类名对动态方法(函数)进行操作

类名.__dict__["方法名"] 或 类名.方法名 都只能查,不能增删改

类调用函数必须给self赋值,哪怕赋的值是无用的,不然根据函数位置参数定义,就会因缺少参数报错

对象:
1、对象查看对象中所有的属性:对象名.__dict__ (因为对象没有建立自己的方法,故此时只能返回属性的字典)
2、对象对对象本身的属性的操作
  方法1、对象名.属性 可以增删改查
  方法2、对象名.__dict__[属性名] 可以增删改查 ******不用*****

3、对象对类中静态字段的操作
3.1、对类静态变量(字段)的操作:只能查,不能增删改
3.2、对类方法的操作:只能引用,不能增删改

self 是位置参数,默认接收的是对象的对象空间,约定俗成叫self

在类的非__init__方法中,也可以给对象添加一些属性,但如要使用这些属性,前提必须先执行这个方法

类一旦创建了,就会执行里面的代码块,如果里面有print语句,就会执行,不像函数要调用才执行

类 只能操作自己的属性及方法,无法操作对象的属性和方法,因为每个对象的属性都是自己独有的

类属性的补充
1、查看类的属性和方法
dir(类名) ----->返回名字列表
类名.__dict__ ----->返回一个字典
2、特殊的类属性
类名.__name__ # 类的名字
类名.__doc__ # 类的文档字符串
类名.__base__ # 类的第一个父类名(继承中从左到右)
类名.__bases__ # 类的所有父类 -----> 返回一个元组
类名.__dict__ # 类的所有属性与方法
类名.__module__ # 类定义所在的模块 【在类所在的脚本中执行和 print(__name__) 一样都是固定的名字:__main__】
类名.__class__ # 实例对应的类(仅新式类中)

四、类与对象的命令空间


创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

静态属性就是直接在类中定义的变量(静态变量或者叫静态字段)

动态属性就是定义在类中的方法

类的静态属性是共享给所有对象的

类的动态属性是绑定到所有对象的

创建一个对象/实例就会创建一个对象/实例的名称空间(开始里面只有对应类对象的指针,以便找到类的__init__()方法来传空间地址及封装对象属性),存放对象/实例的名字,称为对象/实例的属性

对象的查询顺序:先从对象空间去找,对象的空间没有此变量或者方法,通过对象中的类对象指针去类中寻找.

类的查询顺序: 直接从类本身找.它无法查找对象的属性,因为是不同的命名空间

无论创建多少个对象,都是独立开辟的命名空间,各个空间互相不能查找,干扰
  1. 计算一个类实例化了多少个对象?

class Test:
    count = 0

    def __new__(cls, *args, **kwargs):
        cls.count += 1
        return object.__new__(cls)

    def __init__(self):
        pass
print(Test.count)

五、类的三大特性

继承

Python中一个类可以继承一个或多个父类,父类称为基类,子类称为派生类

作用:代码重用,规范接口,统一调用【规范调用方式,调用者不用关心实现】

class A:
    pass
class B:
    pass
class C(A,B):
    pass
# 上面就是基本的一个继承关系,C类分别继承了A,B类的所有属性和方法,C类实现的实例都可以访问
# 但有一点,如果子类和父类都有相同的方法,优先执行子类自己的方法
# 所有的类,都继承基类Object类

# 查看继承关系
C.__bases__

# 查看是否为某个类的对象【开发中经常使用】
instance(obj,cls)
如:instance("china",str)

# 查看是否为某个类的子类
issubclass(cls,fater_cls)

# 接口类
定义一个抽象类,为一组子类定义一个通用的api,使调用方式统一,且接口类是不可以实例化的
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        """通过装饰器,标识为抽象方法,所有子类都需实现本方法"""
        return

# a = Payment()  # Can't instantiate abstract class Payment with abstract methods pay

class UnionPay(Payment):
    def __init__(self, year):
        self.year = year

    def pay(self, money):
        """如果这里不实现此方法,就无法实例化"""
        print("222")

u = UnionPay("2021")  # Can't instantiate abstract class UnionPay with abstract methods pay

封装
隐藏对象的属性和实现细节,仅提供公共访问方式,我们实例化调用init就是一种封装

私有属性
Python中将在类中以双划线开头定义的变量或方法,称为私有属性或方法,仅提供给类内部调用


class Test(object):

    def __init__(self, action):
        self.action = action

    def __smoke(self):
        """此方法仅仅用于类内部调用"""
        print(f"class want ro {self.action}")

    def wash(self):
        print(self.__smoke())
        print(f"wash your {self.action}")

t = Test("face")
t.wash()
t.somke()   # AttributeError: 'Test' object has no attribute 'somke'

静态属性、静态方法、类方法


class Test(object):
    __TYPE = "python小白养成记"

    def __init__(self, action):
        self.__action = action

    @property
    def do(self):
        return f"I can do:{self.__action}"

    @do.setter
    def do(self, v):
        """改变do返回的值"""
        self.__action = v

    @do.deleter
    def do(self):
        print("delete instance property is ok")

    @staticmethod
    def show_action():
        """静态方法:实现普通方法,不需调用实例属性和方法"""
        print("just a ordinary function")

    @classmethod
    def action(cls):
        """类方法"""
        return cls.__TYPE

    def __repr__(self):
        return f"just print the object instance:{self.__action}"

t = Test("eat")

# 静态属性property
将类中方法实现的能力,调用时以属性的方式调用
print(t.do)  # I can do:eat
t.do = "kiss"
print(t.do)  # I can do:kiss
del t.do  # Exception: can't delete instance property

# 静态方法 staticmethod
类中实现的方法,非实例方法,第一个参数不是self,就相当于普通方法
t.show_action()

# 类方法,调用方为类,虽然对象也可以调用,但不建议
t.action()

多态
python天生多态,一类事物有多种状态,相同的需求不同的对象接收时执行不同的行为,但响应的接口是一致的

如:list、dict、set三种不同的对象,要删除元素,都实现了pop方法,虽然他们内部执行的逻辑不同,这就是pop的多种状态

反射【非常重要】
官方定义:程序可以访问、检测和修改它本身状态或行为的一种能力

小白解析:通过字符串的形式操作对象的属性【Python中的哲学:一切皆对象】

hasattr(obj,name) 对象是否有某个属性
getattr(obj,name,default=None) 获取对象的某个属性,如果没有则返回默认值
setattr(obj,name,value) 为对象设置一个属性name,其值为value
delattr(obj,name) 删除对象的某个属性,如果该属性不存在则抛出异常

# 示例:
class Test(object):
    def __init__(self, code, desc):
        self.code = code
        self.desc = desc

    def biz(self):
        return dict(code=self.code, desc=self.desc)

obj = Test(0, "success")

# 判断
print(hasattr(obj, "code"))  # True
# 获取
fun = getattr(obj, "biz", "没有该属性时返回的值,不配置时为None")
print(fun())  # {'code': 0, 'desc': 'success'}
# 设置新属性
setattr(obj, "data", lambda self: dict(self.biz()))
print(obj.data(obj))  # {'code': 0, 'desc': 'success'}

# 删除属性
delattr(obj, "code")

# 查看对象的所有属性
print(obj.__dict__)  # {'desc': 'success', 'data': <function <lambda> at 0x000001E0835DE8C8>}

# py文件也是对象,验证test.py文件中是否有某个方法
import test
if hasattr(test,"func"):
    ret = getattr(test,"func")("args")
    print(ret)

常见的魔法方法

__new__(cls)   对象的构造方法
__init__(self) 对象的初始化方法
__call__(self,*args,**kwargs) 类的实例化对象如函数一般调用,obj=A(),obj(a,b)
__del__(self)  析构方法,释放内存,动用del obj时使用,Python内部自动触发内存回收机制

__repr__(self) 友好的以字符串显示对象,而不是一个内存地址空间,调用repr()方法
__str__(self)  友好的以字符串显示对象,调用srt()方法
__dir__(self)  显示对象的方法与属性,调用dir()

__getattr__(self,name)  定义调用方试图获取一个不存在属性时的动作
__setattr__(self,name,value)  定义当一个属性被设置时的行为
__delattr__(self,name)  定义当一个属性被删除时的行为

__getitem__(self,key)   定义获取容器指定元素的行为,相当于self[key]
__setitem__(self, key, value)  定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)  定义删除容器中指定元素的行为,相当于 del self[key]

__enter__(self)  
1. 定义当使用 with 语句时的初始化行为
2. __enter__ 的返回值被 with 语句的目标或者 as 后的名字绑定
__exit__(self, exc_type, exc_value, traceback)
1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作

猜你喜欢

转载自blog.51cto.com/15127518/2683520