Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Recipe 20.12. Using Cooperative Super calls with Terser Syntax


Credit: Michele Simionato, Gonçalo
Rodrigues


Problem


You like the cooperative style of multiple-inheritance coding
supported by the super built-in, but you wish you
could use that style in a more terse and direct way.


Solution


A custom metaclass lets us selectively wrap the methods exposed by a
class. Specifically, if the second argument of a method is named
super, then that argument gets bound to the
appropriate instance of the built-in super:

import inspect
def second_arg(func):
args = inspect.getargspec(func)[0]
try: return args[1]
except IndexError: return None
def super_wrapper(cls, func):
def wrapper(self, *args, **kw):
return func(self, super(cls, self), *args, **kw)
# 2.4 only: wrapper._ _name_ _ = func._ _name_ _
return wrapper
class MetaCooperative(type):
def _ _init_ _(cls, name, bases, dic):
super(MetaCooperative, cls)._ _init_ _(cls, name, bases, dic)
for attr_name, func in dic.iteritems( ):
if inspect.isfunction(func) and second_arg(func) == "super":
setattr(cls, attr_name, super_wrapper(cls, func))
class Cooperative:
_ _metaclass_ _ = MetaCooperative


Discussion


Here is a usage example of the custom metaclass presented in this
recipe's Solution, in a typical toy case of
"diamond-shaped" inheritance:

if _ _name_ _ == "_ _main_ _":
class B(Cooperative):
def say(self):
print "B",
class C(B):
def say(self, super):
super.say( )
print "C",
class D(B):
def say(self, super):
super.say( )
print "D",
class CD(C, D):
def say(self, super):
super.say( )
print '!'
CD( ).say( )
# emits: B D C !

Methods that want to access the super-instance just need to use
super as the name of their second argument; the
metaclass then arranges to wrap those methods so that the
super-instance gets synthesized and passed in as the second argument,
as needed.

In other words, when a class cls, whose
metaclass is MetaCooperative, has methods whose
second argument is named super, then, in those
methods, any call of the form super.something(*args,
**kw)
is a shortcut for super(cls,
self).something(*args
, **kw). This
approach avoids the need to pass the class object as an argument to
the built-in super.

Class cls may also perfectly well have
other methods that do not follow this convention, and in those
methods, it may use the built-in super in the
usual way: all it takes for any method to be
"normal" is to
not use super as the name of
its second argument, surely not a major restriction. This recipe
offers nicer syntax sugar for the common case of cooperative
supercalls, where the first argument to super is
the current classnothing more.


See Also


Library Reference and Python in a
Nutshell
docs on module inspect and
the super built-in.


/ 394