I needed help on this one. How do I convert a string into a variable/object/instance name, since I don't know how to categorize this. Assuming my code is:
a = {}
b = {}
class Test:
def getKeys(self, var):
return var.keys() #where var refers to the dictionary and its a string initially
It's been forever since I've done anything with Python but I do remember having this problem once. I suggest you look into the eval() function.
If I understand correctly, your variable var is a string that might be "a" or "b". You want to use that letter to pick the correct dictionary global variable to look in.
I suggest putting your dictionaries into another dictionary, with keys you can use to look it up by name:
my_dicts = {"a":a, "b":b}
class Test:
def getkeys(self, dict_name):
return my_dicts[dict_name].keys()
However, this may be simply an issue of design. Instead of sending a variable name to the getkeys method, why not simply send the dictionary itself and use your current code?
Instead of Test().getkeys("a"), call Test().getkeys(a) (no quotation marks).
You're looking for the setattr builtin method. You'll also need an object to perform this on.
obj = lambda: None # Create an empty object without needing to make a class (functions are objects)
setattr(obj, "hello", "world")
obj.hello # returns "world"
Related
I stumbled upon a low-level Python problem that I cannot understand. I want to do something to a string inside a function and keep those alterations.
name = 'name'
def get_new_name(name):
name = 'new_name'
get_new_name(name)
print(name) # expected 'new_name', got 'name'
I would expect that I get new_name printed, however, the result is name.
I know I could get what I want by using return in the function, but can I somehow use a void-like function as described here to get what i want?
You cannot modify immutable objects in python, no. Any reassignment does not modify the original object, but simply changes the reference that the variable points to.
With mutable objects, you can modify it contents, and the changes will be seen when accessing the object via any variables/references that point to it.
Understanding the difference between objects and references is the key to understanding this.
Since you're curious to know if this is possible... it is! But only if you wrap your string inside something else, say, a dict.
def get_new_name(d):
d['name'] = 'new_name'
name = 'name'
d = {'name' : name}
get_new_name(d)
name = d['name']
print(name)
'new_name'
You'd also need to decide on some protocol that you and the function agree upon for smooth communication between each other.
Sure, you could also use a global variable, but your question wasn't really about that... and I wouldn't recommend doing it either - it's bad practice to create impure functions.
Don't pass name to the function, and change the value of the global one. But it's not recommended...
def get_new_name():
global name
name = 'new_name'
your name variable in your void function is only local and does not share the same scope as your global variable name. Once your function finishes running, it discards the local variable with 'new_name' in it. Unless you include the print statement inside the function, which is pretty redundant.
If you want to simply access a global variable you just use its name.
However to change its value you need to use the global keyword.
From https://stackoverflow.com/a/10588342/6225257
I have a dictionary, and a print statement as follows:
d = {'ar':4, 'ma':4, 'family':pf.Normal()}
print(d)
Which gives me
{'ar': 4, 'ma': 4, 'family': <pyflux.families.normal.Normal object at 0x11b6bc198>}
Is there any way to clean up the value of the 'family' key? It's important that the calls remains simply 'print(d)' because it used to print other dictionaries without this issue. Is this possible? Thanks for your time.
EDIT:
Thanks for the answer guys, I would mark one as right but I haven't tried them and can't confirm. I ended up creating another dictionary with the cleaned up string as a key, and the object as the value. It was a bit more work but I did it before reading/getting the responses so I just stuck to it. Thanks nonetheless!
You are mistaken. You don't want to change what print(dict) outputs. That would require changing the way builtin dictionaries are printed. You want to add a custom __repr__() to your pf.Normal() object.
I believe pf.Normal() comes from the pyflux package, so I suggest seeing what data the class is suppose to hold, and pretty printing it by inheriting from the class:
class CustomNormalObject(pf.Normal):
def __repr__(self):
# Add pretty printed data here
pass
Or if you need to pass your own arguments into the custom class, you can use super():
class CustomNormalObject(pf.Normal):
def __init__(self, myparm, *args, **kwargs):
# If using Python 3, you can call super without
# passing in any arguments. This is simply for Python 2
# compatibility.
super(CustomNormalObject, self).__init__(*args, **kwargs)
self.myparm = myparm
def __repr__(self):
# Add pretty printed data here
pass
as I think pyflux is an external library, I think you should not edit it directly. An easy way to do what you want is to overwrite the __str__ or __repr__ methods of the Normal class.
pyflux.families.normal.Normal.__str__ = lambda self: "Clean up value here."
Here I used a lambda function for illustration, but of course you can use a defined function.
Let's say I have a code like this:
def read_from_file(filename):
list = []
for i in filename:
value = i[0]
list.append(value)
return list
def other_function(other_filename):
"""
That's where my question comes in. How can I get the list
from the other function if I do not know the value "filename" will get?
I would like to use the "list" in this function
"""
read_from_file("apples.txt")
other_function("pears.txt")
I'm aware that this code might not work or might not be perfect. But the only thing I need is the answer to my question in the code.
You have two general options. You can make your list a global variable that all functions can access (usually this is not the right way), or you can pass it to other_function (the right way). So
def other_function(other_filename, anylist):
pass # your code here
somelist = read_from_file("apples.txt")
other_function("pears.txt.", somelist)
You need to "catch" the value return from the first function, and then pass that to the second function.
file_name = read_from_file('apples.txt')
other_function(file_name)
You need to store the returned value in a variable before you can pass it onto another function.
a = read_from_file("apples.txt")
There are at least three reasonable ways to achieve this and two which a beginner will probably never need:
Store the returned value of read_from_file and give it as a parameter to other_function (so adjust the signature to other_function(other_filename, whatever_list))
Make whatever_list a global variable.
Use an object and store whatever_list as a property of that object
(Use nested functions)
(Search for the value via garbage collector gc ;-)
)
Nested functions
def foo():
bla = "OK..."
def bar():
print(bla)
bar()
foo()
Global variables
What are the rules for local and global variables in Python? (official docs)
Global and Local Variables
Very short example
Misc
You should not use list as a variable name as you're overriding a built-in function.
You should use a descriptive name for your variables. What is the content of the list?
Using global variables can sometimes be avoided in a good way by creating objects. While I'm not always a fan of OOP, it sometimes is just what you need. Just have a look of one of the plenty tutorials (e.g. here), get familiar with it, figure out if it fits for your task. (And don't use it all the time just because you can. Python is not Java.)
I apologize for the newbie question, but this is my first time working with classes. The class I'm trying to create is intended to perform a regex find and replace on all keys and values within a dictionary. The specific find and replace is defined upon instantiation.
There are two issues that I have. The first issue is that each instance of the class needs to accept a new dictionary. I'm not clear on how to create a class that accepts a general dictionary which I can specify upon creating an instance.
The second issue is that the class I have simply isn't working. I'm receiving the error message TypeError: expected string or buffer in the class line v = re.sub(self.find,self.replace,v).
There are three instances I want to create, one for each input dictionary: input_iter1, input_iter2, and input_iter3.
The following is the class:
class findreplace:
values = []
keys = []
def __init__(self, find, replace):
self.find = find
self.replace = replace
def value(self):
for k,v in input_iter1.items():
v = re.sub(self.find,self.replace,v)
findreplace.values.append(v)
def key(self):
for k,v in input_iter1.items():
k = re.sub(self.find,self.replace,k)
findreplace.keys.append(k)
The following are the instances:
values1 = findreplace('[)?:(]','')
values1.value()
values2 = findreplace(r'(,\s)(,\s)(\d{5})({e<=1})',r'\2\3')
values2.value()
keys1 = findreplace(r'(?<=^)(.+)(?=$)',r'(?:\1)')
keys1.key()
keys2 = findreplace(r'(?=$)',r'{e}')
keys2.key()
print values
print keys
If anyone has any insight on how I can workaround these two issues, I'd be grateful to hear them. Thanks!
First, Python 2 classes should start off this way:
class Foo(object):
Otherwise, you get an "old-style class", which is some ancient crusty thing no one uses.
Also, class names in Python are typically written in CamelCase.
Second, do not use mutable values (like lists!) as class attributes, as you're doing here with keys and values. They'll be shared across all instances of your class! It looks like you're even aware of this, since you refer to findreplace.keys directly, but it doesn't make sense to store instance-specific values in a class attribute like that.
But, most importantly: why is this a class at all? What does a findreplace represent? It looks like this would be much clearer if it were just a single function.
To answer your actual questions:
You pass in a dictionary just like you're passing in find and replace. Add another argument to __init__, and pass another argument when you construct your class.
Presumably, you're getting the TypeError because one of the values in your dictionary isn't a string, and you can only perform regexes on strings.
Where is your definition of the input_iter dicts? How do they look like? Your error indicates that the values of your dicts are not strings.
I have a bunch of variables that are equal to values pulled from a database. Sometimes, the database doesn't have a value and returns "NoneType". I'm taking these variables and using them to build an XML file. When the variable is NoneType, it causes the XML value to read "None" rather than blank as I'd prefer.
My question is: Is there an efficient way to go through all the variables at once and search for a NoneType and, if found, turn it to a blank string?
ex.
from types import *
[Connection to database omitted]
color = database.color
size = database.size
shape = database.shape
name = database.name
... etc
I could obviously do something like this:
if type(color) is NoneType:
color = ""
but that would become tedious for the 15+ variables I have. Is there a more efficient way to go through and check each variable for it's type and then correct it, if necessary? Something like creating a function to do the check/correction and having an automated way of passing each variable through that function?
All the solutions given here will make your code shorter and less tedious, but if you really have a lot of variables I think you will appreciate this, since it won't make you add even a single extra character of code for each variable:
class NoneWrapper(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, name):
value = getattr(self.wrapped, name)
if value is None:
return ''
else:
return value
mydb = NoneWrapper(database)
color = mydb.color
size = mydb.size
shape = mydb.shape
name = mydb.name
# All of these will be set to an empty string if their
# original value in the database is none
Edit
I thought it was obvious, but I keep forgetting it takes time until all the fun Python magickery becomes a second nature. :) So how NoneWrapper does its magic? It's very simple, really. Each python class can define some "special" methods names that are easy to identify, because they are always surrounded by two underscores from each side. The most common and well-known of these methods is __init__(), which initializes each instance of the class, but there are many other useful special methods, and one of them is __getattr__(). This method is called whenever someone tries to access an attribute. of an instance of your class, and you can customize it to customize attribute access.
What NoneWrapper does is to override getattr, so whenever someone tries to read an attribute of mydb (which is a NoneWrapper instance), it reads the attribute with the specified name from the wrapped object (in this case, database) and return it - unless it's value is None, in which case it returns an empty string.
I should add here that both object variables and methods are attributes, and, in fact, for Python they are essentially the same thing: all attributes are variables that could be changed, and methods just happen to be variables that have their value set to a function of special type (bound method). So you can also use getattr() to control access to functions, which could lead to many interesting uses.
The way I would do it, although I don't know if it is the best, would be to put the variables you want to check and then use a for statement to iterate through the list.
check_vars = [color,size,shape,name]
for var in check_vars:
if type(var) is NoneType:
var = ""
To add variables all you have to do is add them to the list.
If you're already getting them one at a time, it's not that much longer to write:
def none_to_blank(value):
if value is None:
return ""
return value
color = none_to_blank(database.color)
size = none_to_blank(database.size)
shape = none_to_blank(database.shape)
name = none_to_blank(database.name)
Incidentally, use of "import *" is generally discouraged. Import only what you're using.
you can simply use:
color = database.color or ""
another way is to use a function:
def filter_None(var):
"" if (a is None) else a
color = filter_None(database.color)
I don't know how the database object is structured but another solution is to modify the database object like:
def myget(self, varname):
value = self.__dict__[varname]
return "" if (value is None) else value
DataBase.myget = myget
database = DataBase(...)
[...]
color = database.myget("color")
you can do better using descriptors or properties