Preparing on Python: Seven refined recipes for programmers
1. Simple tests with use of exceptions
Usually Python it is simple, but there are some unexpected exceptions.
Responds: Robin Parma
Problem
You want to learn{find out}, whether represents contents of a line the whole, and it is far from being the same when you check, whether the line only contains figures.
The decision
* try/except, as a rule, the best approach to the decision of similar problems.
def IsInt (str):
"" Is the given string an integer? ""
try:int (str)
except ValueError:return 0
else:return 1
Discussion
Use exceptions to carry out simple tests which otherwise are tiresome. If you want to know, whether represents contents of a line the whole, simply try to transform her{it}. It also does{makes} IsInt (). The algorithm try/except intercepts exception which is raised when the line cannot be transformed into the whole, and transforms her{it} into harmless return 0. The operator else which is carried out only when any exception is not raised in the operator try, returns 1, if with a line that's all right.
Be not mistaken concerning a word "exception" or that in other languages is considered good style of programming. Use of exceptions and try/except - useful idiom Python.
2. Constants in Python
Free Python will allow you to appropriate{give} new value of any variable; nevertheless, there is a copy in which you can protect the variables.
Responds: Alex Martelli
Problem
It is necessary for you to define{determine} variables at a level of the module, as, for example, " the called constants " (" named constants ") which the client code cannot casually appropriate{give} new values.
The decision
* It is required Python 2.1 or is higher. Insert in const.py the following:
class _Constants:
class ConstError (TypeError): pass
def __ setattr __ (self, name, value):
if self. __ dict __.has_key (name):
raise self. ConstError, " Can't rebind const (%s) " %name
self. __ dict __ [name] = value
def __ delattr __ (self, name):
if self. __ dict __.has_key (name):
raise self. ConstError, " Can't unbind const (%s) " %name
raise NameError, name
import sys
sys.modules [__ name __] = _Constants ()
* now any client-code can:
import const
* and bind an attribute ONCE:
const.magic =23
* but NOT re-bind it:
* const.magic =88 * would raise const. ConstError
Discussion
At will on Python by any variable new value can be appropriated{given}. Modules do not allow you to define{determine} special methods as, for example, __ setattr __ a copy, to prevent pereprisvoenie attribute. The easy decision (on Python 2.1 and is higher) - to use a copy in quality of "module".
Python 2.1 and above any more does not demand, that elements in sys.modules were objects of the module. You can establish there object of a copy and use special methods of access to attribute while the client code will reach still to it{him} with import somename. Probably, to you will seem, what is it concerns to "pitonovskoj" to idiom Singleton (however, see also " Singleton more likely? Yes this is not necessary for us pity Singleton: Borg's method "). Notice, that this "recipe" provides constant linkage with the given name, but not stability of object, that accomplished{perfect} other question.
3. Singleton? Yes this is not necessary for us pity Singleton: Borg's method (Borg)
Beginning{Starting} programmers invariable ask how to write Singleton on Python. The page created Jon Bentley, Martelli, offers us this magnificent sample of programming on Python.
Responds: Alex Martelli
Problem
You have thought, that want to guarantee, that one copy of a class is created only, but then have realized, that actually it is important for you id () copies, how much their status and behaviour not so much.
The decision
Class Borg:
__ shared_state = {}
def __ init __ (self):
self. __ dict __ = self. __ shared_state
* and whatever else you want in your class-that's all!
Discussion
At patternogo designing (design pattern, DP) Singleton an attractive name, but incorrect focus: on individuality, instead of a status. Borg's method instead of it assumes, that all copies divide{share} the general{common} status, and Python allows to achieve it without the slightest efforts.
Notice, that __ getattr __ and __ setattr __ are not involved - they can be determined independently, with any other purpose you not want, or are left uncertain (and itself __ setattr __ if he is determined, it is not caused for pereprisvaivanija __ dict __). It works only with " classical classes " (Python 2.1 or is lower, or for the classes which are not inherited from built - in types Python 2.2 or is higher) as their copies store{keep} all them poehkzempljarnoe a status in classes self __ dict. Classes-2.2 with self. __ slots __ does not support this idiom so smoothly (at desire you can use functions of installation / reception of values (getters/setters) for such expanded, nonclassical classes to cope with this question, but adhere to " classical classes " for these needs{requirements} can to be easiest).
Patternoe designing Singleton basically guarantees, that one copy of the certain class is created only. It has received an attractive name (as well as the general{common} recognition that tries to cope with often present senses) and consequently it is extremely popular. However, by my experience, very much often such designing not the best decision for those senses - it displays various types of problems in various objects - models. That we really would like - and it is typical - so it is an opportunity of creation stol`kikh copies, how much it is necessary, but all with the general{common} status. Who excited with individuality and behaviour? - that us usually disturbs a status. This alternative Pattern (Pattern) has been named the Monostatus (Monostate). In this connection I would like to name Singleton "Gorcem" ("Highlander") as " there can be only one ".
There is a set of ways of realization of the Monostatus on Python, but Borg's approach is frequently the best way. His{its} main force - simplicity. As self. __ dict __ any copy (on Python 2.1 or is lower, or for classical classes on Python 2.2) can be appropriated{given} new value, is simple pereprisvojte it{him} in __ init __ to the dictionary of class - attribute - and all! Now any link or assignment of attribute of a copy will operate equally on all copies - " all of us are uniform ", and so on. David Esher (David Ascher) has offered for this approach very much suitable name - "Borg". It not a pattern as during publication he{it} did not have well-known users. Two or more separate known users - necessary preliminary conditions patternogo designing!
To name this "recipe" " Individual a subject " (" a Singleton ") also it is silly how to count a canopy a umbrella{parasol}. Both of them can be used with the identical purpose (you can walk, not having become wet under a rain) - to resolve similar senses, being expressed by language patternogo designing - but as they do{make} it completely differently, they are not copies of the same pattern. Anyway, as it was mentioned above, Borg is similar alternative patternomu to designing of Monostatus Singleton (but the Monostatus is patternoe designing, and Borg him{it} is not, and, really, Monostatus Python can exist simply fine and not being Borg).
On not clear for me to the reason people often unite the problems, concerning to Borg and "Gorcu" (Highlander), with other questions which are orthogonal as, for example, management of access and - is especial - access from numerous strings. If you need to supervise the reference{manipulation} to object, for this problem{task} all the same, whether there is one or twenty three copies of a class of this object, as well as, whether divide{share} these numerous copies the general{common} status whether or not. " Divide{Share} and dominate " - the effective approach to the decision of problems - to simplify problems, "display" them on components. An example of the approach " unite and be tormented " the connection of several aspects resulting{bringing} in complication of problems is.
4. The parameters of function connected with curry
What for the cookbook without the recipe of preparation of the dish seasoned karri, sharp Indian spice? This widespread idiom of programming gives to your programs aroma of clearness.
Respond: Scott David Denielz, Ben Uolfson, Nik Perkinz, Alex Martelli
Problem
It is necessary for you to wrap up function, or other caused structure, to receive one more caused structure with smaller number of formal arguments, saving values of some initial arguments without change - is exact how when it is necessary for you to fill in caused structure to create another.
The decision
Class curry:
def __ init __ (self, fun, *args, ** kwargs):
self.fun = fun
self.pending = args [:]
self.kwargs = kwargs.copy ()
def __ call __ (self, *args, ** kwargs):
if kwargs and self.kwargs:
kw = self.kwargs.copy ()
kw.update (kwargs)
else:
kw = kwargs or self.kwargs
return self.fun (* (self.pending + args), ** kw)
Discussion
Karring (currying) is a method, nazvanyj in honour of great mathematics KHaskella Karri (Haskell Curry) which allows to connect arguments with function and to expect, while other arguments will not appear later. You "season" (" curry in ") function in several first parameters, and you have a function which accepts the subsequent parameters as arguments, and then causes initial with all these parameters. This "recipe" uses a copy of a class to hold karrirovanye arguments while they will not be necessary for use. For example:
double = curry (operator.mul, 2)
triple = curry (operator.mul, 3)
Karring often it is carried out with lambda forms, but the selected class more clearly and is more legible. Typical use curry - designing of functions of callback (callback functions) for operations GUI. When operation actually does not deserve a new name of function, curry can be useful at creation of such small functions. It can be correct for buttons Tkinter, for example:
self.button=Button (frame, text ='A ',
command=curry (transcript.append, 'A'))
Curry it is possible to use online also for creation of versions of your functions with corresponding debugging default values or the initial parameters filled for your current case. For example, job on debugging a database could begin from installation:
Connect = curry (ODBC.Connect, dsn ='MyDataSet ')
Another example of curry in debugging is wrapping methods:
def report (originalFunction, name, *args, ** kw):
print " %s (%s) " % (name, ', '.join (map (repr, args) +
[k + '=' + repr (kw [k]) for k in kw.keys ()]))
result = originalFunction (*args, ** kw)
if result is not None: print name, ' ==> ', result
return result
class Sink:
def write (self, text): pass
dest = Sink ()
dest.write = curry (report, dest.write, 'write')
print>> dest, ' this', 'is', 1, 'test'
If you create function for constant use, and there is an opportunity of a choice of a name, the form def fun (... Definitions of function often is more legible and easily extends. Curry it is necessary to use when you feel, that with it{him} the code will be clearer, than without him{it}. Usually it emphasizes, that you give parameters only in "usually used" (in this application) function, instead of give separate processing.
You can pass the designer of a class to create illusion of a derivative class:
BlueWindow =curry (Window, background = "blue")
Certainly, BlueWindow (). __ class __ still Windows, instead of the derivative class but if you change only default settings, instead of behaviour, in any case karring is more pertinent, than the task of a derivative class. Besides you can pass additional parameters in karrirovanyj the designer.
5. A factorial with lambda
This "recipe" - only a joke. He a little bit skilful, and we doubted whether to show it{him} to you, but could not be kept: lambda, rekursija, the three-local operator (ternary operator) - all in one line, definitely, from it will be begun to whirl a head of any teacher of a rate of " the Basis of programming ".
Responds: Anurag Unija
Problem
You want to write recursive function, as, for example, a factorial, using ljambda. (it is Possible, you have argued, what is it it is possible to make!)
The decision
f = lambda n: n-1 +abs (n-1) and f (n-1) *n or 1
This "recipe" realizes recursive definition of function of a factorial as lambda forms. As lambda forms should be expressions, it is a little bit odd. If/else directive is not supposed inside expression. Nevertheless, the short-circuited form of idiom Python for " the conditional (three-local) operator " copes with it (other ways of modelling of the three-local operator as short-circuited, and no, see in " Modelling of the three-local operator " v " the Help management{manual} on Python ").
The real problem, certainly, will be, what time a strength lambda in creation of anonymous functions, how we carry out rekursiju? Due to this moment of given "recipe" you can unequivocally win binge against the friends and familiar which use Python, but precipitately have not read from cover to cover it " the Help management{manual} on Python ". Certainly, do not forget to say, that in conditions of a bet it is mentioned only lambda and it is not spoken, that resulting function should be left anonymous! The some people will decide, that you swindle, but we, "pitonovcy", prefer to count ourselves group of pragmatists.
6. Throwing playing bones
We are not sure, whether this "recipe" for his{its} originality is pleasant, or we shall begin to hate it{him} for his{its} ambiguity! He can be confusing but if your cycle for only summarizes objects, think how to simplify this "recipe".
Problem
You need to generate the random numbers feigning throwing of several playing bones provided that the number of bones and number of the parties{sides} of each bone are parameters.
The decision
import random
def dice (num, sides):
return reduce (lambda x, y, s=sides:x +random.randrange (s),
range (num+1)) +num
Discussion
This "recipe" represents simple, but the graceful function, allowing to generate random numbers with the help of simulation of dicing. Number of bones and number of the parties{sides} of each bone - parameters of this function. To stop 4d6 (four bones with six parties{sides}) you would need to call function dice (4,6). Simulation of throwing of a bone very good way of generation of a random number with an expected "binomial" structure. For example, 4d6 will generate a curve (the truth, discrete) probabilities kolokoloobraznoj forms with average 10,5.
Having tried more "manual" approach (a cycle for c the accumulating adder), I have found out, that simplification raises speed. Probably, this realization could be faster as I not profiliroval her{it} am too vigorous; for my purposes she fast enough:).
7. Execute a call of a method for RPC (the removed call of procedure), based on XML
It is necessary for you to execute a call of a method on RPC server, based on XML.
The decision
*needs Python 2.2 or xmlrpclib
from xmlrpclib import Server
server = Server (" http: // www.oreillynet.com/meerkat/xml-rpc/server.php ")
class MeerkatQuery:
def __ init __ (self, search, num_items=5, descriptions=0):
self.search = search
self.num_items = num_items
self.descriptions = descriptions
q = MeerkatQuery (" [Pp] ython ")
print server.meerkat.getItems (q)
Discussion
RPC, based on XML - the simple and easy approach to the distributed{allocated} processing library xmlrpclib which allows to write easily on Python clients RPC on XML and is a part of base library Python since Python 2.2 though you can find her{it} for more "ancient" versions Python on:
www.pythonware.com/products/xmlrpc/.
This "recipe" uses service Meerkat from O'Reilly, intended for association of contents, as, for example, news and announcements of products. Namely, "recipe" requests at Meerkat five latest elements, mentioning either "Python", or "python". If you will try it, mean, that time of the answer from Meerkat can be very various depending on quality of connection, time of day and a level of the traffic through the Internet: if a lot of time for the answer to this scratch is required, it does not mean at all, that you have made something incorrectly - simply it is necessary for you to be typed{collected} patiences!

|