python创建父类对象参数传入问题
class DahlBookManager(models.Manager):
def get_query_set(self):
return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')
这段自定义模型manager的代码里面 用super(DahlBookManager, self)这样的方式构造一个父类对象为什么要传一个DahlBookManager类名和self引用啊? DahlBookManager这个作为参数准确的说是一个DahlBookManager的对象吧? 也就是想问这个构造父类对象的super方法中为什么要传入这样两个参数?
也许可以认为这是Python设计的缺陷导致的,因为Python 3.0只需要用 super().some_attr
就行了。至于为什么需要两个参数,可以大概分析一下,如果有错,欢迎指正。
先介绍下背景知识:super是从Python 2.2开始随着 new-style class
一起引入的,也只能应用于所谓的 new-style class
(即直接或间接继承于 object
的class),可以在一定程度上解决所谓钻石继承
的问题。2.2起所有python内置class都是new-style class。
那么super是什么呢?实际上它是一个builtin的type,你调用 super(Base, self)
会返回一个 __class__ = super
的对象,这个对象可以作为一个代理,通过BFS的顺序(实际上列表已经保存在Base.__mro__
里了)去访问第一个直接定义了目标属性的基类里的属性。super(type, obj_or_subtype).attr
基本上可以认为是 find_in_mro_provide_by(obj_or_subtype, "attr")
,有点晦涩。
注意,super()返回的不是“父类对象”,而是一个super类型的对象;实例化的时候,第一个参数是一个类型(type),第二个参数可以是type的instance,也可以是type的subclass。这两点题主都理解错了。
介绍完基础知识,可以先说说为什么要有第二个参数。理由很简单 —— 我们知道 self 代表当前对象,每个对象的方法在定义的时候都需要显示地把self作为第一个参数,你本来应该写成这样
some_class.some_method(obj, *args, **kwargs)
但是因为Python语法允许 obj.some_metod(*args, **kwargs)
(本质上是个语法糖) ,所以你可以写得简单点(不必显式地给出方法的第一个参数)。而super对象则不同,它没有语法上的直接支持,所以在内部invoke some_method的时候必须指定某个对象,而这个对象的得你自己塞给它,也就是说把这个super对象绑定(bound)到第二个参数上。所以实际上并不是非要用self作为super的第二个参数,甚至super并不是必须在class内部才能调用:
class A(object):
def foo(self):
print self.name
class B(A):
def __init__(self, name):
self.name = name
b1 = B('b1')
super(B, b1).foo() #produces 'b1'
至于为什么要有第一个参数,如果你看了 help(super)
就会发现它居然提供了个单参数的版本:
这个理解起来比较困难点。先说这个unbound
,没绑定,就是说这个super对象没有实际绑定到某个对象上,它并不是可以直接用的。要怎么用呢?那就得注意到help(super)
里面有一个 __get__
方法,也就是说,super类还是一个Descriptor类!哎,这个Descriptor类展开又是好大一段,简单地说就是它可以把自己和某个object的属性绑定,使得访问这个属性的时候,实际上是在调用它的__get__/__set__
方法:
class Descr(object):
def __get__(self, obj, tp): #最后一句传进来的 obj=x, tp=X
return 'get!'
class X(object):
t = Descr()
x = X()
print x.t #this produces 'get!'
回到unbound super, 为了使用它,就要通过 get 方法把它再绑定到一个对象上。由于Descriptor的属性,特别适合这么用:
class A(object):
def foo(self):
print 'foo'
class B(A):
def foo(self):
self._super.foo()
B._super = super(B) #这还不能直接写在B的定义里,多蛋疼啊。
b = B()
b.foo() #produces 'foo'
这是它的一个可能用法。我不确定是否还有其他更合适的用途,但是在这里实际上也并不是很好,尤其是遇到staticmethod的时候还会出错,再加上绕了这么大一个弯,实在不是很推荐使用。
据说unbound super的使用非常少,不知道现实意义有多少,也不知道当初为什么设计成这个样子,总之由于Python3.0已经改了(虽然仍然保留了unbound super),所以基本上还是可以认为这是设计的历史遗留问题。
参考文献(unbound super主要参考了这个系列):Things to Know About Python Super
[1] http://www.artima.com/weblogs/viewpost.jsp?thread=236275
[2] http://www.artima.com/weblogs/viewpost.jsp?thread=236278
[3] http://www.artima.com/weblogs/viewpost.jsp?thread=237121
玩蛇网文章,转载请注明出处和文章网址:https://www.iplaypy.com/wenda/wd20120.html
相关文章 Recommend
- • 2019年3月最新消息: Python 3.4.10 现已推出
- • [上海]招Python量化系统开发工程师
- • 优集品网络科技有限公司招Python中/高级工程师
- • 爱因互动科技发展有限公司招募Python开发攻城狮
- • mozio招聘Python/Django工程师
- • Kavout金融科技公司招Python研发工程师
- • Python数组逆向输出,编程练习题实例四十
- • Python数组插入排序,编程练习题实例三十九
- • Python矩阵for循环应用,编程练习题实例三十八
- • Python操作Redis数据库方面的问题
- • 请python高手帮我看看这段python代码中函数setter的
- • Python什么方法可以快速将两个队列变成字典
必知PYTHON教程 Must Know PYTHON Tutorials
- • python 解释器
- • python idle
- • python dir函数
- • python 数据类型
- • python type函数
- • python 字符串
- • python 整型数字
- • python 列表
- • python 元组
- • python 字典
- • python 集合
- • python 变量
- • python print
- • python 函数
- • python 类定义
- • python import
- • python help
- • python open
- • python 异常处理
- • python 注释
- • python continue
- • python pass
- • python return
- • python global
- • python assert
- • python if语句
- • python break
- • python for循环
- • python while循环
- • python else/elif
- • lambda匿名函数
必知PYTHON模块 Must Know PYTHON Modules
- • os 模块
- • sys 模块
- • re 正则表达式
- • time 日期时间
- • pickle 持久化
- • random 随机
- • csv 模块
- • logging 日志
- • socket网络通信
- • json模块
- • urlparse 解析URL
- • urllib 模块
- • urllib2 模块
- • robotparser 解析
- • Cookie 模块
- • smtplib 邮件
- • Base64 编码
- • xmlrpclib客户端
- • string 文本
- • Queue 线程安全
- • math数学计算
- • linecache缓存
- • threading多线程
- • sqlite3数据库
- • gzip压缩解压
最新内容 NEWS
- • django app提供pv信息的方法是什么
- • Django项目版本升级如何操作?
- • django较多数据传递如何优雅的呈现
- • django1.7获取参数问题求助
- • Django1.7使用内置comment遇到问题
- • python mysql数据库做insert操作时报_mysql_ex
- • 关于python mysql的duplicate insert机制的疑问
- • pymongo使用insert函数批量插入被中断要怎么
- • Python程序员解决棘手问题的常用库
- • 求助关于restfull api接口几个问题
图文精华 RECOMMEND
-
django1.7获取参数问题求助
-
Python程序员解决棘手问题的常用库
-
求问str()同__str__原理上有什么不同
-
scrapy框架里面用link extractor怎么能
-
python {}.fromkeys创建字典append添加操
-
python3 类型Type str doesn't support th
热点文章 HOT
- 学习Python有什么好的书籍推荐?
- Python匿名函数 Lambda表达式作用
- Python与Java、C、Ruby、PHP等编程语言有什么
- Python 正则中文网页字符串提取问题
- 如何为实时性应用存取经纬度?django my
- 想用python做个客户端,在二维码登录这个地
- 有让IDE可识别Python函数参数类型的方法吗
- Python字符串转换成列表正则疑问