Is it possible to translate function, methods, etc. in Python? - python

I know how to have Python localize output of functions, at least anything involving strings. Lots of good questions here about that. I want to do something possible more stupid, but also more basic.
Realistically, it is a handicap that most (popular?) languages are in English of one kind or another. Okay, we deal with that. But what about when creating my own stuff?
class Tomato:
def __init__(self,color):
self.color = color
Happily I can then do
> T = Tomato('red')
> T.color
'red'
Suppose I want to localize not the color name, but the word color itself - or Tomato. So that someone else could do, e.g. in German
> T = Tomate('rot')
> T.farbe
'rot'
without having to know English, or for me to have to write some app interface that exposes only strings to the user.
How the heck would one wrap the original stuff in gettext or friends to do that? Is it even possible? I am assuming the answer is no, or I would have found it. But ... is there any language that would support this kind of thing? It would seem very useful. (Please don't troll me if this is a dumb question, instead please explain why this sort of thing doesn't seem to be even on the radar screen.)

Yeah, dunno how dynamic you could make this, but here's a look:
The weird type() behavior is inspired by
http://www.jeffknupp.com/blog/2013/12/28/improve-your-python-metaclasses-and-dynamic-classes-with-type/
class Tomato(object):
def __init__(self,color):
self.color = color
T = Tomato('red')
T.color
di_trad = {"Tomato": "Tomate"}
def xlator(self, attrname):
di = {"farbe":"color"}
attr_eng = di.get(attrname,attrname)
return getattr(self, attr_eng)
this works... but only because Tomate is hardcoded... You wouldn't want to do this, but it is shows you the basic idea.
Tomate = type("Tomate",(Tomato,),dict(__getattr__=xlator))
t = Tomate('rot')
print t.farbe
#to me this is the weak point ... emitting arbitrary dynamic classnames
#into the current module. mind you, we really want to do this against
#say an import german module...
# and we want to allow drive which classes we translate dynamically as well
Same dynamic generation below, but nothing is harcoded about Tomato or Tomate here. Same idea as above, but you drive the translation by looping through a dict and assigning to a translation support module.
di_class_trad = {"Tomato" :"Tomate"}
import german
for engname, tradname in di_class_trad.items():
cls_ = globals().get(engname)
setattr(german, tradname, type(tradname,(cls_,),dict(__getattr__=xlator)))
#in any case
t2 = german.Tomate("blau")
print t2.farbe
which outputs:
rot
blau
BTW, the contents of the german.py above are just:
pass
Note that the translation routines are driven by dictionaries so in theory it is pretty dynamic.
I would keep all the attributes in one dictionary, not a per-class dictionary. Then, as you go through farbe/color, height/höhe, width/breite translation pairs, you'd want to check that the translated class (Tomato) had that property (width) before assigning its translation, breite, to class Tomate.
Regarding dynamic properties, this is a tweak of what Sublime Text generates as a property skeleton. If you drove it with a loop for the xlator dictionary and assigned the property to the target class, who knows, it might work...
def farbe():
doc = "The farbe property."
def fget(self):
return self.color
def fset(self, value):
self.color = value
def fdel(self):
del self.color
return locals()
#farbe = property(**farbe())
#would this work?
setattr(tgt_class,"farbe", property(**farbe()))
Cute, but again, not sure how much real use this would be, unless you keep the actual user-visible translated capabilities to pretty basic manipulation. It might help to assign Tomate a second ancestor class in the type call to add some brains to keep sanity.
i.e.
setattr(german, tradname, type(tradname,(cls_,SanityManagerClass),dict(__getattr__=xlator))

Related

Converting a String into a variable

For my examine command, because I don't want to do this:
def examine(Decision):
if Decision == "examine sword":
print sword.text
elif Decision == "examine gold":
print gold.text
elif Decision == "examine cake":
print cake.text
...
for every item in my game.
So I wanted to convert the second word of the Decision string into a variable so that I could use something like secondwordvar.text.
I tried to use eval(), but I always get an errors when I make a spelling mistake in a single word command.
The error
IndexError: list index out of range
It's be working otherwise though.
Right now my code is this:
def exam(Decision):
try:
examlist = shlex.split(Decision)
useditem = eval(examlist[1])
print useditem.text
except NameError:
print "This doesn't exist"
Does anyone have an idea, for an other option, how I could write that function in a easy way?
I should probably also include the full game. You can find it here:
http://pastebin.com/VVDSxQ0g
Somewhere in your program, create a dictionary mapping the name of the object to a variable that it represents. For example:
objects = {'sword': sword, 'gold': gold, 'cake': cake}
Then you can change your examine() function to something like the following:
def examine(Decision):
tokens = shlex.split(Decision)
if len(tokens) != 2 or tokens[0] != 'examine' or tokens[1] not in objects:
print "This doesn't exist"
else:
print objects[tokens[1]].text
What you could do (because with my knowledge in programming, somewhat limited, this is the most advanced way I could see it) is to utilize dictionaries. I'll try to explain in english, because my knowledge of code in this field is suspect and I don't want to mislead you.
Dictionaries are very array-like, allowing you to associate a decision with a value.
You would be able to associate Examine sword with an action code 4
This would (in a hack-y way) allow you to convert your string to a variable, more by direct and consistent referencing of key/value pairs.
Good luck with this approach; Read up some on Dictionaries and you may very well find them easier to handle than it sounds!
Finally, as a form of good coding practice, never use eval() unless you are sure of what you are doing. eval() executes the code inside the (), so if, god forbid, some malicious process manages to run that code with a malicious line injected inside it:
eval(###DELETE EVERYTHING RAWR###)
You'll have a bad time. Sincerely.
Also, for the sake of evaluating code, I've heard that it is a very slow command, and that there are better alternatives, performance-wise.
Happy coding!
These two print the same text:
Using a dictionary:
texts = dict(sword = "wathever",
gold = "eachever",
cake = "whomever")
def examine_dict(decision):
decision = decision.split()[1]
print texts[decision]
examine_dict("examine sword")
Using object attributes (a class):
class Texts():
sword = "wathever"
gold = "eachever"
cake = "whomever"
def examine_attribute(decision):
decision = decision.split()[1]
text = getattr(Texts, decision)
print text
examine_attribute("examine sword")
Depending on what you want, one method can be more appropriate than the other. The dictionary-based method, however, is in general, the easier and the faster one.
Your variables are stored in a dictionary somewhere. If they are global variables, globals() returns this dictionary. You can use this to look up the variable by name:
globals()['sword'].text
If the variables are stored in a class as attributes, you can use getattr:
getattr(object, 'sword').text
You'll want to catch possible exceptions for bad names.

Is there a reason not to send super().__init__() a dictionary instead of **kwds?

I just started building a text based game yesterday as an exercise in learning Python (I'm using 3.3). I say "text based game," but I mean more of a MUD than a choose-your-own adventure. Anyway, I was really excited when I figured out how to handle inheritance and multiple inheritance using super() yesterday, but I found that the argument-passing really cluttered up the code, and required juggling lots of little loose variables. Also, creating save files seemed pretty nightmarish.
So, I thought, "What if certain class hierarchies just took one argument, a dictionary, and just passed the dictionary back?" To give you an example, here are two classes trimmed down to their init methods:
class Actor:
def __init__(self, in_dict,**kwds):
super().__init__(**kwds)
self._everything = in_dict
self._name = in_dict["name"]
self._size = in_dict["size"]
self._location = in_dict["location"]
self._triggers = in_dict["triggers"]
self._effects = in_dict["effects"]
self._goals = in_dict["goals"]
self._action_list = in_dict["action list"]
self._last_action = ''
self._current_action = '' # both ._last_action and ._current_action get updated by .update_action()
class Item(Actor):
def __init__(self,in_dict,**kwds)
super().__init__(in_dict,**kwds)
self._can_contain = in_dict("can contain") #boolean entry
self._inventory = in_dict("can contain") #either a list or dict entry
class Player(Actor):
def __init__(self, in_dict,**kwds):
super().__init__(in_dict,**kwds)
self._inventory = in_dict["inventory"] #entry should be a Container object
self._stats = in_dict["stats"]
Example dict that would be passed:
playerdict = {'name' : '', 'size' : '0', 'location' : '', 'triggers' : None, 'effects' : None, 'goals' : None, 'action list' = None, 'inventory' : Container(), 'stats' : None,}
(The None's get replaced by {} once the dictionary has been passed.)
So, in_dict gets passed to the previous class instead of a huge payload of **kwds.
I like this because:
It makes my code a lot neater and more manageable.
As long as the dicts have at least some entry for the key called, it doesn't break the code. Also, it doesn't matter if a given argument never gets used.
It seems like file IO just got a lot easier (dictionaries of player data stored as dicts, dictionaries of item data stored as dicts, etc.)
I get the point of **kwds (EDIT: apparently I didn't), and it hasn't seemed cumbersome when passing fewer arguments. This just appears to be a comfortable way of dealing with a need for a large number of attributes at the the creation of each instance.
That said, I'm still a major python noob. So, my question is this: Is there an underlying reason why passing the same dict repeatedly through super() to the base class would be a worse idea than just toughing it out with nasty (big and cluttered) **kwds passes? (e.g. issues with the interpreter that someone at my level would be ignorant of.)
EDIT:
Previously, creating a new Player might have looked like this, with an argument passed for each attribute.
bob = Player('bob', Location = 'here', ... etc.)
The number of arguments needed blew up, and I only included the attributes that really needed to be present to not break method calls from the Engine object.
This is the impression I'm getting from the answers and comments thus far:
There's nothing "wrong" with sending the same dictionary along, as long as nothing has the opportunity to modify its contents (Kirk Strauser) and the dictionary always has what it's supposed to have (goncalopp). The real answer is that the question was amiss, and using in_dict instead of **kwds is redundant.
Would this be correct? (Also, thanks for the great and varied feedback!)
I'm not sure I understand your question exactly, because I don't see how the code looked before you made the change to use in_dict. It sounds like you have been listing out dozens of keywords in the call to super (which is understandably not what you want), but this is not necessary. If your child class has a dict with all of this information, it can be turned into kwargs when you make the call with **in_dict. So:
class Actor:
def __init__(self, **kwds):
class Item(Actor):
def __init__(self, **kwds)
self._everything = kwds
super().__init__(**kwds)
I don't see a reason to add another dict for this, since you can just manipulate and pass the dict created for kwds anyway
Edit:
As for the question of the efficiency of using the ** expansion of the dict versus listing the arguments explicitly, I did a very unscientific timing test with this code:
import time
def some_func(**kwargs):
for k,v in kwargs.items():
pass
def main():
name = 'felix'
location = 'here'
user_type = 'player'
kwds = {'name': name,
'location': location,
'user_type': user_type}
start = time.time()
for i in range(10000000):
some_func(**kwds)
end = time.time()
print 'Time using expansion:\t{0}s'.format(start - end)
start = time.time()
for i in range(10000000):
some_func(name=name, location=location, user_type=user_type)
end = time.time()
print 'Time without expansion:\t{0}s'.format(start - end)
if __name__ == '__main__':
main()
Running this 10,000,000 times gives a slight (and probably statistically meaningless) advantage passing around a dict and using **.
Time using expansion: -7.9877269268s
Time without expansion: -8.06108212471s
If we print the IDs of the dict objects (kwds outside and kwargs inside the function), you will see that python creates a new dict for the function to use in either case, but in fact the function only gets one dict forever. After the initial definition of the function (where the kwargs dict is created) all subsequent calls are just updating the values of that dict belonging to the function, no matter how you call it. (See also this enlightening SO question about how mutable default parameters are handled in python, which is somewhat related)
So from a performance perspective, you can pick whichever makes sense to you. It should not meaningfully impact how python operates behind the scenes.
I've done that myself where in_dict was a dict with lots of keys, or a settings object, or some other "blob" of something with lots of interesting attributes. That's perfectly OK if it makes your code cleaner, particularly if you name it clearly like settings_object or config_dict or similar.
That shouldn't be the usual case, though. Normally it's better to explicitly pass a small set of individual variables. It makes the code much cleaner and easier to reason about. It's possible that a client could pass in_dict = None by accident and you wouldn't know until some method tried to access it. Suppose Actor.__init__ didn't peel apart in_dict but just stored it like self.settings = in_dict. Sometime later, Actor.method comes along and tries to access it, then boom! Dead process. If you're calling Actor.__init__(var1, var2, ...), then the caller will raise an exception much earlier and provide you with more context about what actually went wrong.
So yes, by all means: feel free to do that when it's appropriate. Just be aware that it's not appropriate very often, and the desire to do it might be a smell telling you to restructure your code.
This is not python specific, but the greatest problem I can see with passing arguments like this is that it breaks encapsulation. Any class may modify the arguments, and it's much more difficult to tell which arguments are expected in each class - making your code difficult to understand, and harder to debug.
Consider explicitly consuming the arguments in each class, and calling the super's __init__ on the remaining. You don't need to make them explicit:
class ClassA( object ):
def __init__(self, arg1, arg2=""):
pass
class ClassB( ClassA ):
def __init__(self, arg3, arg4="", *args, **kwargs):
ClassA.__init__(self, *args, **kwargs)
ClassB(3,4,1,2)
You can also leave the variables uninitialized and use methods to set them. You can then use different methods in the different classes, and all subclasses will have access to the superclass methods.

How to write a function to return the variable name?

I want a function that can return the variable/object name as str like this :
def get_variable_name (input_variable):
## some codes
>>get_variable_name(a)
'a'
>>get_variable_name(mylist)
'mylist'
it looks like silly but i need the function to construct expression regarding to the variable for later on 'exec()'. Can someone help on how to write the 'get_variable_name' ?
I've seen a few variants on this kind of question several times on SO now. The answer is don't. Learn to use a dict anytime you need association between names and objects. You will thank yourself for this later.
In answer to the question "How can my code discover the name of an object?", here's a quote from Fredrik Lundh (on comp.lang.python):
The same way as you get the name of that cat you found on your porch:
the cat (object) itself cannot tell you its name, and it doesn’t
really care — so the only way to find out what it’s called is to ask
all your neighbours (namespaces) if it’s their cat (object)…
….and don’t be surprised if you’ll find that it’s known by many names,
or no name at all!
Note: It is technically possible to get a list of the names which are bound to an object, at least in CPython implementation. If you're interested to see that demonstrated, see the usage of the inspect module shown in my answer here:
Can an object inspect the name of the variable it's been assigned to?
This technique should only be used in some crazy debugging session, don't use anything like this in your design.
In general it is not possible. When you pass something to a function, you are passing the object, not the name. The same object can have many names or no names. What is the function supposed to do if you call get_variable_name(37)? You should think about why you want to do this, and try to find another way to accomplish your real task.
Edit: If you want get_variable_name(37) to return 37, then if you do a=37 and then do get_variable_name(a), that will also return 37. Once inside the function, it has no way of knowing what the object's "name" was outside.
def getvariablename(vara):
for k in globals():
if globals()[k] == vara:
return k
return str(vara)
may work in some instance ...but very subject to breakage... and I would basically never use it in any kind of production code...
basically I cant think of any good reason to do this ... and about a million not to
Here's a good start, depending on the Python version and runtime you might have to tweak a little. Put a break point and spend sometime to understand the structure of inspect.currentframe()
import inspect
def vprint(v):
v_name = inspect.currentframe().f_back.f_code.co_names[3]
print(f"{v_name} ==> {v}")
if __name__ == '__main__':
x = 15
vprint(x)
will produce
x ==> 15
if you just want to return the name of a variable selected based on user input... so they can keep track of their input, add a variable name in the code as they make selections in addition to the values generated from their selections. for example:
temp = raw_input('Do you want a hot drink? Type yes or no. ')
size = raw_input('Do you want a large drink? Type yes or no. ')
if temp and size == 'yes':
drink = HL
name = 'Large cafe au lait'
if temp and size != 'yes':
drink = CS
name = 'Small ice coffee'
print 'You ordered a ', name, '.'
MJ
If your statement to be used in exec() is something like this
a = ["ddd","dfd","444"]
then do something like this
exec('b = a = ["ddd","dfd","444"]')
now you can use 'b' in your code to get a handle on 'a'.
Perhaps you can use traceback.extract_stack() to get the call stack, then extract the variable name(s) from the entry?
def getVarName(a):
stack = extract_stack()
print(stack.pop(-2)[3])
bob = 5
getVarName(bob);
Output:
getVarName(bob)

A more pythonic way to build a class based on a string (how not to use eval)

OK.
So I've got a database where I want to store references to other Python objects (right now I'm using to store inventory information for person stores of beer recipe ingredients).
Since there are about 15-20 different categories of ingredients (all represented by individual SQLObjects) I don't want to do a bunch of RelatedJoin columns since, well, I'm lazy, and it seems like it's not the "best" or "pythonic" solution as it is.
So right now I'm doing this:
class Inventory(SQLObject):
inventory_item_id = IntCol(default=0)
amount = DecimalCol(size=6, precision=2, default=0)
amount_units = IntCol(default=Measure.GM)
purchased_on = DateCol(default=datetime.now())
purchased_from = UnicodeCol(default=None, length=256)
price = CurrencyCol(default=0)
notes = UnicodeCol(default=None)
inventory_type = UnicodeCol(default=None)
def _get_name(self):
return eval(self.inventory_type).get(self.inventory_item_id).name
def _set_inventory_item_id(self, value):
self.inventory_type = value.__class__.__name__
self._SO_set_inventory_item_id(value.id)
Please note the ICKY eval() in the _get_name() method.
How would I go about calling the SQLObject class referenced by the string I'm getting from __class__.__name__ without using eval()? Or is this an appropriate place to utilize eval()? (I'm sort of of the mindset where it's never appropriate to use eval() -- however since the system never uses any end user input in the eval() it seems "safe".)
To get the value of a global by name; Use:
globals()[self.inventory_type]

What's the best way to initialise and use constants across Python classes?

Here's how I am declaring constants and using them across different Python classes:
# project/constants.py
GOOD = 1
BAD = 2
AWFUL = 3
# project/question.py
from constants import AWFUL, BAD, GOOD
class Question:
def __init__(self):
...
Is the above a good way to store and use contant values? I realise that after a while, the constants file can get pretty big and I could explicitly be importing 10+ of those constants in any given file.
why not just use
import constants
def use_my_constants():
print constants.GOOD, constants.BAD, constants.AWFUL
From the python zen:
Namespaces are good. Lets do more of those!
EDIT: Except, when you do quote, you should include a reference and check it, because as others have pointed out, it should read:
Namespaces are one honking great idea -- let's do more of those!
This time, I actually copied it from the source: PEP 20 -- The Zen of Python
You also have the option, if the constants are tied to a particular class and used privately within that class of making them specific to that class:
class Foo(object):
GOOD = 0
BAD = 1
WTF = -1
def __init__(self...
and away you go.
You have a few options:
Do it the way you're doing right now with a file of constants
Use a flat file and parse it once, pass a dictionary / class around
Query off to a database
From an overhead point of view, 1 and 2 are about the same. As for your question about importing specific constants, it's much easier to use one of the following conventions:
import constants; some_func(constants.AWFUL)
from constants import *; some_func(AWFUL)
Try to look at the following links(one link contains a receipt from active state of how to implement a real constants):
Importing a long list of constants to a Python file
Create constants using a "settings" module?
Can I prevent modifying an object in Python?
I use a function as immutable constant, like this:
def test_immutable_constant():
def GOOD():
return 1
good_value = GOOD()
good_value = 2
assert GOOD() == 1
assert good_value == 2

Categories

Resources