python3对类中的方法限制比python2放的更开了

作为一个python老鸟,最近在辅导一个同事学习python,她提出了一些稀奇古怪的问题,比如在我的意识中,下面的代码是肯定运行不了的

# coding:utf-8
class Test(object):
    def print_name(name):
        print(name)

Test.print_name("ali")

因为在类里如果一个方法没有任何装饰器(比如classmethod/staticmethod)装饰的话,那么它就是一个实例方法,至少需要一个参数,而且第一个参数就是实例本身(不管它叫啥,一般叫self),所以用类名直接调用实例方法肯定是不行的!我也是这么跟她解释的,但是,奇怪的事情发生了,她竟然运行出来了,而且结果正确!我当时都懵逼了!尴了个尬,尬了个尴!
我第一反应就是本地运行,结果确实报错了!和我预期的一样

TypeError: unbound method print_name() must be called with Test instance as first argument (got str instance instead)

唯一区别就是我用的是python2,她用的是python3。

下面先说说我的大胆猜测和验证工作吧!
py3对类中的方法限制比py2放的更开了!
py3更显著的支持“鸭子类型”,也就是说它不管你传入的类型是什么,只要你传入的对象能满足函数中的使用要求即可–这就需要使用者自己去把控了。比如下面:

class Test(object):
    def __init__(self):
        self.name = "Test"

    def print_name(name):
        print(name)

    def duck_test(self):
        print(self.name)


class Duck(object):
    def __init__(self):
        self.name = "Duck"


Test.print_name("ali")
Test.duck_test(Duck())

输出结果为:
ali
Duck

duck_test明显是一个实例方法,第一个参数为实例本身,py2中必须要用Test的实例去调用才可以,但是py3中我们也可传入一个其它类型的实例,它只需要包含方法中使用到的"name"属性就可正确运行了!这就是鸭子类型,这样方法的使用就更灵活,同时也省略了类型检查-速度会更快(猜测这个才是改变的原因吧)。
类方法也是一样的道理。静态方法就更不必说了!很明显这是py3的一大变化!
需要说明的是:

如果一个方法没有任何装饰器(比如classmethod/staticmethod)装饰的话:
当用实例去调用这个方法时,默认会将实例本身作为第一个参数传入,所以这个方法必须要有一个形参,否则报错!
当用类去调用这个方法时,类会将这种方法当作一个普通方法去调用(网上说py3比py2在定义类时多了一种普通方法)
(注意只有类去调用classmethod装饰的类方法时,才会将类本身作为第一个参数传入)

供大家参考:
https://github.com/zpoint/CPython-Internals/blob/master/BasicObject/class/class_cn.md
https://www.cnblogs.com/traditional/p/13605011.html

上一篇:python学习——快速入门


下一篇:CentOS 7安装python3