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

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

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

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

David Ascher, Alex Martelli, Anna Ravenscroft

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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


Recipe 6.18. Automatically Initializing Instance Variables from _ _init_ _ Arguments


Credit: Peter Otten, Gary Robinson, Henry Crutcher, Paul
Moore, Peter Schwalm, Holger Krekel


Problem


You want to avoid writing and maintaining _ _init_
_
methods that consist of almost nothing but a series of
self.something = something assignments.


Solution


You can "factor out" the
attribute-assignment task to an auxiliary function:

def attributesFromDict(d):
self = d.pop('self')
for n, v in d.iteritems( ):
setattr(self, n, v)

Now, the typical boilerplate code for an _ _init_
_
method such as:

    def _ _init_ _(self, foo, bar, baz, boom=1, bang=2):
self.foo = foo
self.bar = bar
self.baz = baz
self.boom = boom
self.bang = bang

can become a short, crystal-clear one-liner:

    def _ _init_ _(self, foo, bar, baz, boom=1, bang=2):
attributesFromDict(locals( ))


Discussion


As long as no additional logic is in the body of _ _init_
_
, the dict returned by calling the
built-in function locals contains only the
arguments that were passed to _ _init_ _ (plus
those arguments that were not passed but have default values).
Function attributesFromDict extracts the object,
relying on the convention that the object is always an argument named
'self', and then interprets all other items in the
dictionary as names and values of attributes to set. A similar but
simpler technique, not requiring an auxiliary function,
is:

    def _ _init_ _(self, foo, bar, baz, boom=1, bang=2): 
self._ _dict_ _.update(locals( ))
del self.self

However, this latter technique has a serious defect when compared to
the one presented in this recipe's Solution: by
setting attributes directly into self._ _dict_ _
(through the latter's update
method), it does not play well with properties and other advanced
descriptors, while the approach in this recipe's
Solution, using built-in setattr, is impeccable in
this respect.

attributesFromDict is not meant for use in an
_ _init_ _ method that contains more code, and
specifically one that uses some local variables, because
attributesFromDict cannot easily distinguish, in the
dictionary that is passed as its only argument d,
between arguments of _ _init_ _ and other local
variables of _ _init_ _. If
you're willing to insert a little introspection in
the auxiliary function, this limitation may be overcome:

def attributesFromArguments(d):
self = d.pop('self')
codeObject = self._ _init_ _.im_func.func_code
argumentNames = codeObject.co_varnames[1:codeObject.co_argcount]
for n in argumentNames:
setattr(self, n, d[n])

By extracting the code object of the _ _init_ _
method, function attributesFromArguments
is able to limit itself to the names of
_ _init_ _'s arguments. Your
_ _init_ _ method can then call
attributesFromArguments(locals( )), instead of
attributesFromDict(locals( )), if and when it
needs to continue, after the call, with more code that may define
other local variables.

The key limitation of attributesFromArguments is
that it does not support _ _init_
_
having a last special argument of the
**kw kind. Such support can be added, with yet
more introspection, but it would require more black magic and
complication than the functionality is probably worth. If you
nevertheless want to explore this possibility, you can use the
inspect module of the standard library, rather
than the roll-your-own approach used in function
attributeFromArguments, for introspection purposes.
inspect.getargspec(self._ _init_ _) gives you both
the argument names and the indication of whether self._
_init_ _
accepts a **kw form. See Recipe 6.19 for more information
about function inspect.getargspec. Remember the
golden rule of Python programming: "Let the standard
library do it!"


See Also


Library Reference and Python in a
Nutshell
docs for the built-in function
locals, methods of type dict,
special method _ _init_ _, and introspection
techniques (including module inspect).

/ 394