Discuss / Python / 关于动态类与动态类的实例的区别

关于动态类与动态类的实例的区别

Topic source

Flamsky

#1 Created at ... [Delete] [Delete and Lock User]

发现如下情况

  • Animal或者子类,可以被传入Animal类型变量的函数run_twice()调用
  • Animal或其子类的实例,可以被传入Animal类型变量的函数run_twice()调用
  • Timer类,不可以被传入Animal类型变量的函数run_twice()调用
  • Timer类的实例,可以被传入Animal类型变量的函数run_twice()调用
>>> class Timer(object):
...     def run(self):
...         print('Trickle...trickle...')
... 
>>> run_twice(Timer)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in run_twice
TypeError: run() missing 1 required positional argument: 'self'
>>> t=Timer()
>>> run_twice(t)
Trickle...trickle...
Trickle...trickle...

Flamsky

#2 Created at ... [Delete] [Delete and Lock User]

我搞错了,少打了一副括号

>>> run_twice(Timer())
Trickle...trickle...
Trickle...trickle...

Flamsky

#3 Created at ... [Delete] [Delete and Lock User]

发现根本上是自己的理解有点问题,实际上只要类的名字带上了括号,就已经是一个instance了,只不过run_twice(Timer())没有给这个instance赋予变量名。理解错误。

Baby-amier

#4 Created at ... [Delete] [Delete and Lock User]

请教:run_twice就是一个函数,而不是类的方法,无论什么类传进来,都会打印出两行来,我并没有理解动态语言这种鸭子式的方式。能帮忙解释一下吗?

活力的greg

#5 Created at ... [Delete] [Delete and Lock User]

请教:run_twice就是一个函数,而不是类的方法,无论什么类传进来,都会打印出两行来,我并没有理解动态语言这种鸭子式的方式。能帮忙解释一下吗?

同样的疑问

Slayer_Ni

#6 Created at ... [Delete] [Delete and Lock User]

我是这么理解这个鸭子的 : 对于C++或其他静态语言 run_twice函数在定义时形参的类型就已经确定了 比如上文的Animal类,而调用的时候必须传入Animal类,当传入是Timer类时就会报错。 python由于其动态语言,animal这个变量是可以不限定变量类型的,只要确保他有run这个函数 执行下来就不会报错,这个应该就是所谓的鸭子。

Mr羊习

#7 Created at ... [Delete] [Delete and Lock User]

C/C++这样的静态语言定义函数的时候是需要显式地申明参数类型,既然限定了参数类型自然也限定了参数在函数内的行为,因为错误的参数类型在传入的当下就已经被拒绝接受了。

然而python这样的动态语言函数的参数从来都没有明确申明,因此你传入任何类型,python函数都能接住,不过接住以后函数调用的时候发现该参数并没有某行为的话才会抛出异常,因此只要函数内部调用的行为只要传入参数具备就行。

简而言之,静态语言传参错误,是不会进入函数调用阶段;而动态语言是接收后使用参数的过程中发现错误抛出异常。

我也是没搞懂‘鸭子’的含义 def run_twice(animal): animal.run() 这里的animal又不是Animal,他只是一个形参而已,改成其他名字都没问题吧,只要调用的时候传入一个有run方法的实力对象就ok的吧,望不吝赐教

ksven

#9 Created at ... [Delete] [Delete and Lock User]

是这样的。@Mr羊习 解释的很清楚,Python没有类型检查,语法上只要有run方法的对象都可以传入run_twice方法并且调用对象的run方法,只能自己保证语义上是不是正确。

同意楼上好几个人的那个观点。run_twice就是个普通的函数,和继承没啥关系,更看不出多态的好处在哪里。


  • 1
  • 2

Reply