使用type在对象方法中调用类方法

type简介

type在Python中的作用是创建一个类。

我们创建类的时候一般会使用这样的方法:

# -*- coding:utf-8 -*-

class Student(object):

    country = "China"

    def add(self,x:int,y:int)->int:
        return x+y

s1 = Student()
print(s1.country)
print(s1.add(12,23))

当然也可以使用type方法创建类,效果与上面的方法一样:

# -*- coding:utf-8 -*-
Student = type(
    "Student",
    # 元组只有单个元素后面需要加逗号!
    (object,),
    {
        'country':"China",
        'add':lambda self,x,y:x+y
    }
)

s1 = Student()
print(s1.country)
print(s1.add(12,33))

不过,我最近看公司某个封装好的功能的源码的时候,发现了它另外的一个用途,就是“在对象方法中调用类方法”(什么,你分不清对象方法、类方法与静态方法?请自行Google)。

在对象方法中使用类方法

基本操作

假设我们现在有一个Student类,要在对象方法中调用类方法,可以这样写:

# -*- coding:utf-8 -*-
class Student(object):

    @classmethod
    def get_country(cls):
        return "China"

    def __init__(self,name):
        self.name = name
        # type(self),在对象方法中使用类的方法
        self.country = type(self).get_country()

    def get_my_country(self):
        # type(self),在对象方法中使用类的方法
        return type(self).get_country()

if __name__ == '__main__':
    
    s1 = Student('wanghw')
    
    print(s1.country) # China
    print(s1.get_my_country()) # China
    
    # 事实上,对象也可以直接调用“类方法”,但是为了“规范”,我们不这么直接让对象直接调用“类方法”
    print(s1.get_country()) # China

起一个与类方法同名的对象方法再试试

上面的基本操作也许大家都明白,现在我们试一下极端的方式:起一个与类方法同名的对象方法,看看效果如何:

# -*- coding:utf-8 -*-
class Student(object):

    @classmethod
    def get_country(cls):
        return "China"

    def __init__(self,name):
        self.name = name
        # type(self),在对象方法中使用类的方法
        self.country = type(self).get_country()

    def get_my_country(self):
        # type(self),在对象方法中使用类的方法
        return type(self).get_country()

    # 起一个与类方法同名的对象方法
    def get_country(self):
        return "English"


if __name__ == '__main__':

    s1 = Student('wanghw')

    print(s1.country) 
    print(s1.get_my_country())

运行程序,你会发现上报了一个这样的错误:

TypeError: get_country() missing 1 required positional argument: 'self'

实际上,此时我们实例化的Student对象用的是自己的方法!而上面的__init__初始化方法与get_my_country方法的调用者是类Student,缺少了参数self,我们把程序修改如下(在get_country中加上参数self再试试):

# -*- coding:utf-8 -*-
class Student(object):

    @classmethod
    def get_country(cls):
        return "China"

    def __init__(self,name):
        self.name = name
        # type(self),在对象方法中使用类的方法
        self.country = type(self).get_country(self)

    def get_my_country(self):
        # type(self),在对象方法中使用类的方法
        return type(self).get_country(self)

    # 起一个与类方法同名的对象方法
    def get_country(self):
        return "English"


if __name__ == '__main__':

    s1 = Student('wanghw')

    print(s1.country) # English
    print(s1.get_my_country()) # English

由此,我们可以得出结论:如果对象方法与类方法同名的话,对象会优先调用自己的方法!

其他相关的知识点详见这篇博客

其他关于type的说明,我自己之前总结过一篇关于type与isinstance的区别的文章,还有我在网上找的一篇很不错的关于type的说明的文章:

https://www.cnblogs.com/paulwhw/p/10637282.html

https://www.cnblogs.com/zy0517/articles/9046549.html

posted on 2019-11-06 19:18  江湖乄夜雨  阅读(447)  评论(0编辑  收藏  举报