47.Python对象魔法方法

1.常见魔法

面向对象内置双下__开头的方法也称为魔术方法,简称魔法.
双下__魔法满足条件会自动触发.

1.1初始化对象值

__init__ 调用类实例化自动触发 初始化对象的值
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name


stu1 = student('kid')
print(stu1.name)

1.2打印对象

__str__  输出对象的时候自动触发 打印对象,主动报异常 
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name


stu1 = student('kid')
print(stu1)  # <__main__.student object at 0x0000014F6F239358>
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name

    # 打印对象的时候自动触发
    def __str__(self):
        return '%s同学' % self.name  # 必须是字符串类型


stu1 = student('kid')
print(stu1)  # kid

1.3回收

__del__ 两个触发场景
1.手动执行删除类的属性
2.整个程序执行完毕后回收数据时自动触发
如果手动触发了,就不在自动触发.
# 主动触发
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print('数据被删除')  # 数据被删除



stu1 = student('kid')
del stu1.name
# 自动触发
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print('数据被删除')  # 数据被删除



stu1 = student('kid')

1.4对象调用

__call__ 对象加括号自动触发
class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name


stu1 = student('kid')  # <__main__.student object at 0x0000018BFB3F9358>
print(stu1())  # TypeError: 'student' object is not callable
能加括号调用的,在他的父类中都设置了__call__方法.
num = 1
num()  # TypeError: 'int' object is not callable
"""
1 ==> num = int(1)
int 为类
源码中加上 
__call__ 就能实现加括号调用.
"""
print(int()) 结果为 0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dP1lCbOK-1639036452814)(https://s2.loli.net/2021/12/07/wQchik6AOvsG52Z.png)]

class student():
    # 初始化对象值
    def __init__(self, name):
        self.name = name

    def __call__(self, *args, **kwargs):
        return self.__dict__


stu1 = student('kid')  # <__main__.student object at 0x0000018BFB3F9358>
print(stu1())  # {'name': 'kid'}

1.5关系判断

isinstance(对象, )      判断某个对象是否为 某个类的对象
issubclass(子类, 父类)     判断某个类是否为某个类派生的
class A():
    pass


obj = A()

print(isinstance(obj, A))  # True
class A():
    pass


class B(A):
    pass


print(issubclass(B, A))  # True

2.反射

反射:通过字符串的形式操作对象访问属性或调用方法.
在Python中一切皆对象,都可以使用反射.

2.1.查1

__getatter__  getatter(对象, 属性, 不存在的返回值)
查找属性或方法, 存在返回对应的值,不存在则报错,
可以设置第三个参数不存在的返回来一个值.

返回值是一个函数的内存地址可以加括号进行调用.
class Student():
    school = 'xxx'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print('哇哇哇')


stu = Student('kid', 18)

print(getattr(stu, 'name'))  # kid
print(getattr(stu, 'qq', None))  # AttributeError: 'Student' object has no attribute 'qq'
getattr(stu, 'talk')()  # 加上括号调用 哇哇哇

2.2查2

__hasatter__ 查看对象的名称空间中某个名字,返回为布尔值.
class Student():
    school = 'xxx'

    def __init__(self, name, age):
        self.name = name
        self.age = age
 	

stu = Student('kid', 18)
print(hasattr(stu, 'name'))  # True
print(hasattr(stu, 'qq'))  # False

2.3增改

__setatter__ 修改对象属性或添加属性, 存在则修改 不存在则修改
class Student():
    school = 'xxx'

    def __init__(self, name, age):
        self.name = name
        self.age = age


stu = Student('kid', 18)
print(stu.name)  # kid
setattr(stu, 'name', 'qq')  # 存在则修改
print(stu.name)  # qq
class Student():
    school = 'xxx'

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


stu = Student('kid')

setattr(stu, 'age', 'qq')  # 不存在则新增
print(stu.age)  # qq

2.4删

__delatter__ 对应属性名不存在,会报错,如果存在会直接删除对应属性
class Student():
    school = 'xxx'

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


stu = Student('kid')

delattr(stu, 'age')  # AttributeError: age
class Student():
    school = 'xxx'

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


stu = Student('kid')

delattr(stu, 'name')  # 什么都没有

3.异常

3.1简介

异常:代码运行发送错误的信号,当遇到错误就会抛出异常.程序结束运行.
如果不处理该错误,就永远报错.

3.2分类

异常的分类:
语法错误: 出现因该立刻处理
逻辑错误: 出现了因该尽快处理

3.3语法结构

try:
	被检测的代码
except 错误类型1 as e: # e接收报错的完整信息
	对应的处理机制
except 错误类型1:
	对应的处理机制
except Exception:
	对应的处理机制
else:
    没有被检测到错误运行
finally:
    都会运行

3.4自定义异常

BaseException是所有异常的父类.
继承BaseException类派生子类自定义异常.
class MyExcptipn(BaseException):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg


"""

Traceback (most recent call last):
  File "E:/synchro/Project/pythonProject/1.py", line 9, in <module>
    raise MyExcptipn('这个出现xxx错误!')
__main__.MyExcptipn: 这个出现xxx错误!

"""

raise MyExcptipn('这个出现xxx错误!')

4.二次加工标准类型

Python 为大家提供了标准的数据类型,以及丰富的内置方法其实很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型.
class List(list):

    def append(self, append_obj):
        # 设置限制 只添加 int类型的值否则抛出异常
        if not (isinstance(append_obj, int)):
            raise TypeError('添加的值必须是整型!')
        super().append(append_obj)  # 将自己创建的对象传递到父类中 , 对象调用父类的append方法 追加值


l = list()  # 得到一个空累不
L = List()  # 自动去 找到 list类的__init__ 得到一个空列表
print(l ,L)  # [] []

L.append(1)
L.append(2)
print(L)

image-20211207223744488

5.描述符

描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
描述符的作用:
用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
# 描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')

    def __set__(self, instance, value):
        print('Str设置...')

    def __delete__(self, instance):
        print('Str删除...')


# 描述符Int
class Int:
    def __get__(self, instance, owner):
        print('Int调用')

    def __set__(self, instance, value):
        print('Int设置...')

    def __delete__(self, instance):
        print('Int删除...')


class People:
    name = Str()
    age = Int()

    def __init__(self, name, age):  # name被Str类代理,age被Int类代理,
        self.name = name
        self.age = age


# 何地?:定义成另外一个类的类属性

# 何时?:且看下列演示

p1 = People('alex', 18)

# 描述符Str的使用
p1.name
p1.name = 'egon'
del p1.name

# 描述符Int的使用
p1.age
p1.age = 18
del p1.age

# 查看数据
print(p1.__dict__)  # 被删除  现在为空
print(People.__dict__)  # 类的名称空间

# 补充
print(type(p1) == People)  # type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/121827697
今日推荐