Python基础学习(十二)--魔方方法,is与==,类的常用函数,反射函数

本文深入探讨Python中的魔法方法,包括__del__、__call__、__str__、__repr__、__new__、__eq__、__hash__等,解析它们的作用及应用场景,并通过实例演示如何使用这些方法来增强类的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、常用魔方方法

(一)__del__()方法--销毁魔术方法

当一个对象在内存中被销毁的时候自动执行,至少有一个self参数,接收对象。

程序自动调用此方法,不需要我们手动调用。

class A():
    num=0    # 类属性,也叫静态属性
    def __init__(self,name):
        A.num+=1    # 每定义一个对象,计数器加1
        self.name=name
    def __del__(self):
        A.num-=1
        print(self.name,'被删除,还剩下{}个对象'.format(A.num))
a=A('张三')
b=A('李四')
c=A('王五')
print(A.num)
del a    # 自动调用__del__()
del b
del c

(二)__call__()方法

可以让类的实例具有类似于函数的行为,进一步模糊了函数和对象之间的概念。

对象后面加括号,就像函数一样触发执行。形如:对象名()或类名()()。

class A():
    def __init__(self,num):
        self.num=num
    def __call__(self,n):
        return self.num*n
a=A(7)
print(a(9))
print(A(3)(7))

斐波那契序列

class Fib():
    def __init__(self):
        pass
    def __call__(self,month):
        lst=[]
        a,b=1,1
        n=1
        while n<=month:
            lst.append(a)
            a,b=b,a+b
            n+=1
        return lst
f=Fib()
for i in range(1,10):
    print(f(i))
class Fib():
    def __init__(self):
        pass
    def __call__(self,month):
        a,b=0,1
        n=1
        while n<=month:
            a,b=b,a+b
            n+=1
        return a
f=Fib()
m=int(input('请输入:'))
print(f(m))

(三)__str__()方法和__repr__()方法--改变对象的字符串显示

__repr__()是__str_()方法的备胎,找不到__str__()就会找它。

%s和str()默认调用__str__()。

%r和repr()默认调用__repr__()。

class Per():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return '%s:%d'%(self.name,self.age)
    def __repr__(self):
        return '我叫{},年龄{}'.format(self.name,self.age)
a=Per('张三',19)
print(a)
print(str(a))
print('%s'% a)
print('%r'% a)
print(repr(a))

(四)__new__()方法--实例化魔方方法

在实例化对象是自动触发。

至少有一个cls参数,接收当前类,返回一个对象实例。

先触发__new__()才会触发__init__()。

class Stu():
    # 实例化
    def __new__(cls, *args, **kwargs):
        print('111111111111111111111')
        # 如果不写这句,就没有创建对象,只打印111,不打印222。调用父类的__nuw__()方法就可以创建对象了。
        return object.__new__(cls)
    # 初始化
    def __init__(self,name,age):
        print('222222222222222222222')
        self.name=name
        self.age=age
zs=Stu('张三',19)
print(zs.name)

(五)is和==的区别

is比较两个对象的id值是否相等,是否指向同一个内存地址。

==比较的是两个对象的内容是否相同,默认调用对象的__eq__()方法。

继承自object的__eq__()方法比较两个对象的id。但对于自定义的对象,一般认为对象的值相同就是同一个对象,因此需要复写__eq__()方法。

class Stu():
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __eq__(self, other):    # equal
        return self.__dict__==other.__dict__
a=Stu('张三',19)
b=Stu('张三',19)
c=Stu('李四',20)
print(a==b)    # True
print(a is b)    # False

# !!!重点
d=[]
d.append(a)
if b not in d:    # 去调用了__eq__(),发现a==b,所以列表中只有一个对象。说明这里的in是根据==判断的。
    d.append(b)
print(d)

(六)__hash__()方法--哈希/散列

将一个不定长的输入,通过哈希函数变换成一个定长的输出,即哈希值。

这种哈希变换是一种单向运算,具有不可逆性即不能根据哈希值还原出输入的信息。

set集合要求数据是可哈希的,因为set集合会默认调用对象的__hash__()函数进行快速查询,如果找到了则调用对象的__eq__()函数判断两个是否相同,如果相同则不添加。

在自定义类中,如果没有实现__eq__()和__hash__(),会继承object的__eq__()和__hash__()。如果只定义__eq__()方法,没有定义__hash__(),__hash__()方法会隐式设置为None。

hash()函数默认调用object类的__hash__()方法,Hash值是对象的id值的十六分之一。

class Stu():
    def __init__(self,name):
        self.name=name
a=Stu('张三')
b=Stu('李四')
c=Stu('王五')
s={a,b,c}
print(s)
print(hash(a))
print(id(a)/16)

结果:
{<__main__.Stu object at 0x0000000002877C50>, <__main__.Stu object at 0x0000000001E498D0>, <__main__.Stu object at 0x000000000286D0F0>}
1984909
1984909.0
class Stu():
    def __init__(self,name):
        self.name=name
    def __eq__(self, other):
        print('222')
        return self.name==other.name
    def __hash__(self):
        print('111')
        return hash(self.name)
a=Stu('张三')
b=Stu('李四')
c=Stu('张三')
print(id(a))
print(id(b))
print(id(c))
print(a==c)
d={a,b,c}
print(d)

结果:
42630336
42630224
42683696
222
True
111
111
111
222
{<__main__.Stu object at 0x00000000028A7CC0>, <__main__.Stu object at 0x00000000028A7C50>}

二、类的常用函数

(一)issubclass()--检测一个类,是否为另一个类的子类

格式:issubclass(被检测类,父类)。若一次判断多个父类,有一则为真。

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

(二)isinstance()--检测一个对象是否为某个类的对象

格式:isinstance(对象,类)。若一次判断多个类,有一则为真。

class A():
    pass
a=A()
print(isinstance(a,A))

(三)反射函数

1.hasattr()--判断是否有此变量,返回值为bool类型

2.getattr()--获取属性值或者获取方法变量的地址,返回值为数值

3.delattr()--删除类或者对象的属性或方法

4.setattr()--给类或者对象设置属性或者方法

class A():
    dog=0
    def hehe(num):
        print(num)
setattr(A,'dog',90)
print(A.__dict__)
setattr(A,'cat',10)
print(A.__dict__)

a=A()
print(a.__dict__)
setattr(a,'haha',1999)
print(a.__dict__)
a.hehe=2022
print(a.__dict__)

print(getattr(A,'dog'))
f=getattr(A,'hehe')
f(1)
delattr(A,'dog')
print(hasattr(A,'dog'))
class A():
    def f1(self):
        print('我是f1')
    def f2(self):
        print('我是f2')
    def f3(self):
        print('我是f3')
print(A.__dict__)
a=A()
while True:
    f=input('请输入你想调用的方法:')
    if hasattr(A,f):
        fc=A.__dict__.get(f)
        fc(a)
    else:
        print('A类没有',f)

5.反射导入的模块中的属性、函数、类

t1模块:

d='周2'
def func(a):
    print('你好是函数',a)
class A():
    def __init__(self,name):
        self.name=name

t2:

import t1

x=getattr(t1,'d')
print(x)

f=getattr(t1,'func')
f('张三')

cls=getattr(t1,'A')
a=cls('张三')
print(a.name)

6.反射自己模块中的属性和函数

import sys

zhutou=299
def func():
    print('aaaaaaaaaaaaaaaaa')

# 查看所有模块
print(sys.modules)

# 反射当前模块
print(sys.modules['__main__'])

# 反射当前模块中的zhutou变量
x=getattr(sys.modules['__main__'],'zhutou')
print(x)
x=getattr(sys.modules['__main__'],'func')
x()

7.反射内置模块

import time
print(time.time())
t=getattr(time,'time')
print(t())

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值