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.1. Converting Among Temperature Scales


Credit: Artur de Sousa Rocha, Adde Nilsson


Problem




You want to convert easily among Kelvin,
Celsius, Fahrenheit, and Rankine scales of
temperature.


Solution


Rather than having a dozen functions to do all possible conversions,
we can more elegantly package this functionality into a class:

class Temperature(object):
coefficients = {'c': (1.0, 0.0, -273.15), 'f': (1.8, -273.15, 32.0),
'r': (1.8, 0.0, 0.0)}
def _ _init_ _(self, **kwargs):
# default to absolute (Kelvin) 0, but allow one named argument,
# with name being k, c, f or r, to use any of the scales
try:
name, value = kwargs.popitem( )
except KeyError:
# no arguments, so default to k=0
name, value = 'k', 0
# error if there are more arguments, or the arg's name is unknown
if kwargs or name not in 'kcfr':
kwargs[name] = value # put it back for diagnosis
raise TypeError, 'invalid arguments %r' % kwargs
setattr(self, name, float(value))
def _ _getattr_ _(self, name):
# maps getting of c, f, r, to computation from k
try:
eq = self.coefficients[name]
except KeyError:
# unknown name, give error message
raise AttributeError, name
return (self.k + eq[1]) * eq[0] + eq[2]
def _ _setattr_ _(self, name, value):
# maps settings of k, c, f, r, to setting of k; forbids others
if name in self.coefficients:
# name is c, f or r -- compute and set k
eq = self.coefficients[name]
self.k = (value - eq[2]) / eq[0] - eq[1]
elif name == 'k':
# name is k, just set it
object._ _setattr_ _(self, name, value)
else:
# unknown name, give error message
raise AttributeError, name
def _ _str_ _(self):
# readable, concise representation as string
return "%s K" % self.k
def _ _repr_ _(self):
# detailed, precise representation as string
return "Temperature(k=%r)" % self.k


Discussion


Converting between several different scales or units of measure is a
task that's subject to a
"combinatorial explosion": if we
tackle it in the apparently obvious way, by providing a function for
each conversion, then, to deal with n
different units, we will have to write n *
(n-1)
functions.

A Python class can intercept attribute setting and getting, and
perform computation on the fly in response. This power enables a much
handier and more elegant architecture, as shown in this recipe for
the specific case of temperatures.

Inside the class, we always hold the measurement in one reference
unit or scale, Kelvin (absolute) degrees in the case of this recipe.
We allow the setting of the value to happen through any of four
attribute names ('k', 'r', 'c', 'f', abbreviations
of the scales' names), and compute and set the
Kelvin-scale value appropriately. Vice versa, we also allow the
"getting" of the value in any
scale, through the same attribute names, computing the result on the
fly. (Assuming you have saved the code in this recipe as
te.py somewhere on your Python
sys.path, you can import it as a module.) For
example:

>>> from te import Temperature
>>> t = Temperature(f=70) # 70 F is...
>>> print t.c # ...a bit over 21 C
21.1111111111
>>> t.c = 23 # 23 C is...
>>> print t.f # ...a bit over 73 F
73.4

_ _getattr_ _
and _ _setattr_ _
work better than named properties would in this case, since the form
of the computation is the same for every attribute (except the
reference 'k' one), and we only need to use
different coefficients that we can most handily keep in a per-class
dictionary, the one we name self.coefficients.
It's important to remember that _ _setattr_
_
is called on every setting of any
attribute, so it must delegate to object the
setting of attributes, which need to be recorded in the instance (the
_ _setattr_ _ implementation in this recipe does
just such a delegation for attribute k) and must
raise an AttributeError exception for attributes
that can't be set. _ _getattr_ _,
on the other hand, is called only upon the
"getting" of an attribute that
can't be found by other,
"normal" means (e.g., in the case
of this recipe's class, _ _getattr_
_
is not called for accesses to
attribute k, which is recorded in the instance and
thus gets found by normal means). _ _getattr_ _
must also raise an AttributeError exception for
attributes that can't be accessed.


See Also


Library Reference and Python in a
Nutshell
documentation on attributes and on special
methods _ _getattr_ _ and _ _setattr_
_
.


/ 394