QQ登录

只需一步,快速开始

开启左侧

Python学习第七十二天—类和对象21-type()函数和__init_subclass__

[复制链接]
15271953841 发表于 2024-4-16 10:52:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 15271953841 于 2024-4-19 08:54 编辑

type()函数和__init_subclass__
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
一、type()函数
type(250)
<class 'int'>
type(3.14)
<class 'float'>
type("FishC")
<class 'str'>
当然,现在我们是不推荐使用type()函数来检测对象类型,取而代之是使用isintance()函数会更适合,因为isintance()函数会考虑到子类的情况。
以下红色部分,是补充的内容:
(isinstance) 与 (type) 区别:
(type) 不会认为子类是一种父类类型,不考虑继承关系。
(isinstance) 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 (isinstance)。
isinstance(1, int)
True
isinstance(1.0, float)
True
isinstance(1,(int,float))
True
class Myclass:
pass
test = Myclass
()
isinstance(test, Myclass)
True

isinstance()是 Python 内置函数之一,用于检查一个对象是否属于指定的类型。它的语法为:
isinstance(object, classinfo)
object – 实例对象
classinfo – 可以是直接或间接继承的类、基本类型或者由它们组成的元组。
返回值:如果object 的类型与classinfo相同则返回 True,否则返回 False。
isinstance() 函数的作用和原理如下:
检查对象是否属于指定类型:isinstance() 用于判断一个对象是否是给定类型的实例。如果对象是指定类型的实例,返回 True;
处理继承关系:isinstance() 在检查类型时会考虑继承关系。如果检查的对象是指定类型的子类的实例,也会返回 True。【 type() 不会认为子类是一种父类类型,不考虑继承关系】
处理类型元组:classinfo 参数可以是一个类型元组,即包含多个类型的元组。如果 object 是类型元组中任意一个类型的实例,函数将返回 True
class A:
    pass

class B(A):
    pass

a = A()
b = B()
c = 3
print(isinstance(a, A))          # True,a是A类型的实例
print(isinstance(b, A))          # True,b是A类型子类B的实例(继承关系)
print(isinstance(b, (int, str)))      # False,a不是int或str类型的实例
print(isinstance(c, (int, str)))      # True,c是int或str类型的实例
print(isinstance(B(), A) )   # returns True    如果要判断两个类型是否相同推荐使用 isinstance()
print(isinstance(B, A) )   # returns False   
print(type(a) == A  )   # returns True
print(type(b) == A  )   # returns False  
总之,isinstance() 函数在 Python 中用于检查对象是否属于指定类型,它是处理对象类型的一种常用工具。


int
<class 'int'>
float
<class 'float'>
str
<class 'str'>
type("FishC") is str
True
type(250)("520")                (type(250)此时相当于int)
520
int("520")                      (因为type(250)得到一个int类型<class ‘int’>,然后int(“520”)把它的参数这个字符串”520”转换成整数)
520
type("FishC")(3.14)                (type(“FishC”)此时相当于str)
'3.14'                           (把3.14包成了字符串)
str(3.14)
'3.14'
type([])("FishC")                   (type([])相当于list)
['F', 'i', 's', 'h', 'C']
list("Fish")
['F', 'i', 's', 'h']
type(())([1,1,2,3,5])                  (type(())相当于tuple)
(1, 1, 2, 3, 5)
tuple([1,1,2,3,5])
(1, 1, 2, 3, 5)
type({}).fromkeys("Python")           (type({})相当于dict,参考第31课时fromkeys内置的方法,创建一个新的字典)
{'P': None, 'y': None, 't': None, 'h': None, 'o': None, 'n': None}
dict.fromkeys("Python")
{'P': None, 'y': None, 't': None, 'h': None, 'o': None, 'n': None}
class C:
    def __init__(self,x):
        self.x = x

        
c = C(250)
c
<__main__.C object at 0x000001E68C058470>
d = type(c)(520)              (type(c)相当于class C,就是大C)
d
<__main__.C object at 0x000001E68C058560>
c.__class__            (看一个对象的类型,我们也可以使用__class__属性,返回的结果相对简单一点)
<class '__main__.C'>
d.__class__
<class '__main__.C'>          (返回它的类)
type(C)                (大写C是一个类
<class 'type'>
type(type)
<class 'type'>
type就是根源,Python万物的起点,Pthon万物皆对象,包括生成对象的类其自身其实也是对象,类也是对象,它是由type生成而来的对象,所以我们这里把class C传入type,它得到是<class ‘type’>,那么type又是谁,它是自己的对象,type is type.
type的两种不同的用法:
第一种是根据object参数的类型,返回值是一个type对象,通常与object.__class__,返回的对象相同。
第二种是根据传入的三个参数,返回一个新的type对象。
Class type(name,bases,dict,**kwds)
前三个参数是必选的
name——指定将要创造的类的名称
bases——指定将要创造的类的父类
dict——指定将要创造的类的属性和方法
kwds——(可选)收集参数,当且仅当需要时,该收集参数将被传递给适当的元类机制(通常为__init_subclass__()),3.6版本才添加的)
class C:
    def __init__(self,x):
        self.x = x

        
c = C(250)
c
<__main__.C object at 0x000001E68C058470>
d = type(c)(520)
d
<__main__.C object at 0x000001E68C058560>
c.__class__
<class '__main__.C'>
d.__class__
<class '__main__.C'>
type(C)
<class 'type'>
type(type)
<class 'type'>
list("Fish")
['F', 'i', 's', 'h']
tuple([1,1,2,3,5])
(1, 1, 2, 3, 5)
dict.fromkeys("Python")
{'P': None, 'y': None, 't': None, 'h': None, 'o': None, 'n': None}
class C:
    pass

C = type("C",(),{})
c = C()
c.__class__
<class '__main__.C'>
C.__bases__
(<class 'object'>,)
D = type("D",(C,),{})
D.__bases__
(<class '__main__.C'>,)
E = type("E",(),dict(x=250,y=520))
E.x
250
E.y
520
def func(self,name = "FishC"):
    print(f"Hello {name}")

   
F = type("F",(),dict(say_hi=func))           (函数怎么放到第三个参数里面去呢?之前怎么把函数放到列表中去的?我们并不是直接在列表中定义函数,是先在外面定义好了函数,然后再把函数的函数名放到列表中而已。那么这里也是同样的道理)
f = F()
f.say_hi()
Hello FishC
f.say_hi("小姐姐")
Hello 小姐姐
补充:把函数放到列表中:
# 定义一些函数
def func1():
    print("Function 1")

def func2():
    print("Function 2")

def func3():
    print("Function 3")

# 创建一个包含函数的列表
functions_list = [func1, func2, func3]

# 调用列表中的函数
for func in functions_list:
func()
这段代码定义了三个简单的函数func1, func2, 和 func3,然后创建了一个名为functions_list的列表,其中包含这三个函数。最后,循环遍历这个列表并调用每个函数。


二、__init_subclass__()加强父类对子类的管理
class C:                           (做成一个父类)
    def __init_subclass__(cls):        (它是一个类方法,所以需要绑定一个类cls,第一个参数就是用来绑定类的)
        print("父爱如山~")
        cls.x = 520                  (类的x属性赋值520)

        
class D(C):                           (定义一个子类D,继承自类C)
    x = 250                          (设置一个类属性,把它指定为250)

   
父爱如山~                  (当我们子类D定义完成之后,其父类的__init_subclass__()方法就会被触发,打印“父爱如山~”)
D.x                          (试图访问子类D里的x属性的时候,这就是沉重的父爱感情在子类中赋值的x属性竟然是没有用的)
520
它实现的原理,相当于上一节的类装饰器是一样的,在类定义完成之后,它被拦截了,所以子属性才会被覆盖,
这个__init_subclass__()跟我们type()函数的第四个参数又有什么广西呢?这个__init_subclass__()方法除了第一个参数可以传递类(cls)之外,其实还可以传入其它的参数。
下面重新定义class C:加一个value参数:
class C:
    def __init_subclass__(cls,value):
        print("父爱如山~")
        cls.x = value

        
class D(C,value = 520):             (那么子类在继承父类的时候,参数就应该在写完父类,紧接着使用关键字参数的形式给传递进去)
    x = 250

   
父爱如山~
D.x
520
那么,当我们使用type()函数来构造class D这种继承了定义过__init_subclass__()的父类时,如果需要给__init_subclass__()传递参数,比如这里传递value参数,我们就可以用第四个参数接力了。
class C:
    def __init_subclass__(cls,value1,value2):
        print("父爱如山~")
        cls.x = value1
        cls.y = value2

        
D = type("D",(C,),dict(x=250),value1=520,value2=666)
父爱如山~
D.x
520
D.y
666

客服热线
400-1234-888 周一至周日:09:00 - 21:00
公司地址:襄阳市樊城区长虹路现代城5号楼188

创客帮MAKER.BAND青少年创客创意社区是一个融教育、科技、体育资讯为一体的综合服务平台,专注于教育创新、专注于科技体育、专注于教育资讯。

Powered by Discuz! X3.4 © 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表