I have the following in a Python script:
setattr(stringRESULTS, "b", b)
Which gives me the following error:
AttributeError: 'str' object has no attribute 'b'
Can any-one telling me what the problem is here?
Don't do this. To quote the inestimable Greg Hewgill,
"If you ever find yourself using quoted names to refer to variables,
there's usually a better way to do whatever you're trying to do."
[Here you're one level up and using a string variable for the name, but it's the same underlying issue.] Or as S. Lott followed up with in the same thread:
"90% of the time, you should be using a dictionary. The other 10% of
the time, you need to stop what you're doing entirely."
If you're using the contents of stringRESULTS as a pointer to some object fred which you want to setattr, then these objects you want to target must already exist somewhere, and a dictionary is the natural data structure to store them. In fact, depending on your use case, you might be able to use dictionary key/value pairs instead of attributes in the first place.
IOW, my version of what (I'm guessing) you're trying to do would probably look like
d[stringRESULTS].b = b
or
d[stringRESULTS]["b"] = b
depending on whether I wanted/needed to work with an object instance or a dictionary would suffice.
(P.S. relatively few people subscribe to the python-3.x tag. You'll usually get more attention by adding the bare 'python' tag as well.)
Since str is a low-level primitive type, you can't really set any arbitrary attribute on it. You probably need either a dict or a subclass of str:
class StringResult(str):
pass
which should behave as you expect:
my_string_result = StringResult("spam_and_eggs")
my_string_result.b = b
EDIT:
If you're trying to do what DSM suggests, ie. modify a property on a variable that has the same name as the value of the stringRESULTS variable then this should do the trick:
locals()[stringRESULTS].b = b
Please note that this is an extremely dangerous operation and can wreak all kinds of havoc on your app if you aren't careful.
Related
The usual method of attribute access requires attribute names to be valid python identifiers.
But attributes don't have to be valid python identifiers:
>>> class Thing:
... def __init__(self):
... setattr(self, '0potato', 123)
...
>>> t = Thing()
>>> Thing.__getattribute__(t, '0potato')
123
>>> getattr(t, '0potato')
123
Of course, t.0potato remains a SyntaxError, but the attribute is there nonetheless:
>>> vars(t)
{'0potato': 123}
What is the reason for this being permissable? Is there really any valid use-case for attributes with spaces, empty string, python reserved keywords etc? I thought the reason was that attributes were just keys in the object/namespace dict, but this makes no sense because other objects which are valid dict keys are not allowed:
>>> setattr(t, ('tuple',), 321)
TypeError: attribute name must be string, not 'tuple'
The details from a comment on the post fully answer this question, so I'm posting it as an answer:
Guido says:
...it is a feature that you can use any arbitrary string
with getattr() and setattr(). However these functions should (and do!)
reject non-strings.
Possible use-cases include hiding attributes from regular dotted access, and making attributes in correspondence with external data sources (which may clash with Python keywords). So, the argument seems to be there's simply no good reason to forbid it.
As for a reason to disallow non-strings, this seems to be a sensible restriction which is ensuring greater performance of the implementation:
Although Python's dicts already have some string-only optimizations -- they just dynamically adapt to a more generic and slightly slower approach once the first non-key string shows up.
So, to answer the use case question, looking at the reasoning behind how Python works in the references from the comments above, we can infer some of the situations that might make this Pythonic quirk useful.
You want an object to have an attribute that cannot be accessed with dot notation, say, to protect it from the naive user. (Quoting Guido: "some people might use this to hide state they don't want accessible using regular attribute notation (x.foo)". Of course, he goes on to say, "but that feels like abuse of the namespace to me, and there are plenty of other
ways to manage such state.")
You want an object's attribute names to correspond to external data over which you have no control. Thus, you have to be able to use whatever strings appear in the external data as an attribute name even if it matches a Python reserved word or contains embedded spaces or dashes, etc.
I'm trying to create a system on Python that allows me to create a list called (user)total, 'user' being the name of the user before total. However this is subjective as any account with any username could be made within my program.
I have tried to use
%stotal = [''] %user
however this comes up with a syntax error. How would I manage to do this?
You can't do that kind of meta-programming in python! (not with the syntax you posted)
But instead you can create a dictionary of lists indexed by the user name:
total = {}
total['username1'] = [''] #list for this username total
total['username2'] = ['']
etc.
It is possible. Hopefully seeing how will help to illustrate why, as Hyperboreus says, it's not a good idea.
If you do dir() in your interactive Python environment, you'll get a list of names that are available in your current scope. There will always be one called __builtins__, which exposes all of the functions and constants in the builtins module. These functions and constants are defined to be exactly the same ones that are available right from the start of your Python session in the global namespace, which you can take a look at with the builtin function globals().
In accordance with the Python data model, every Python object has an element named __dict__ that's a dictionary object whose keys are member names. If obj is the name of some Python object in the current scope, obj.__dict__["keyname"] will access the same member that you could get to more simply through obj.keyname.
So putting this together, you can set key/value pairs in __builtins__.__dict__ directly:
>>> __builtins__.__dict__["testvarname"] = "testval"
>>> print testvarname
testval
Whew! Getting pretty abstract pretty quick here. This might be useful for defining behavior based on user input or something else that you might not know until runtime... but you can probably see how you're working through a lot of complexity to get there and sort of circumventing the normal rules that Python sets out to try to help you keep your programs organized and easy to understand. xndrme's answer is likely to be the more straightforward way to solve the bigger problem you're facing.
How can I store values in a list without specifying index numbers?
For example
outcomeHornFive=5
someList = []
someList.append(outComeHornFive)
instead of doing this,
someList[0] # to reference horn five outcome
how can i do something like this? The reason is there are many items that I need to reference within the list and I just think it's really inconvenient to keep track of which index is what.
someList.hornFive
You can use another data structure if you'd like to reference things by attribute access (or otherwise via a name).
You can put them in a dict, or create a class, or do something else. It depends what kind of other interaction you want to have with that object.
(P.S., we call those lists, not arrays).
Instead of using a list you can use a dictionary.
See data types in the python documentation.
A dictionary allows you to lookup a value using a key:
my_dict["HornFive"] = 20
You cannot and you shouldn't. If you could do that, how would you refer to the list itself? And you will need to refer to the list itself.
The reason is there are many items that i need to reference within the list and I just think it's really inconvenient to keep track of which index is what.
You'll need to do something of that ilk anyway, no matter how you organize your data. If you had separate variables, you'd need to know which variable stores what. If you had your way with this, you'd still need to know that a bare someList refers to "horn five" and not to, say, "horn six".
One advantage of lists and dicts is that you can factor out this knowledge and write generic code. A dictionary, or even a custom class (if there is a finite number of semantically distinct attributes, and you'd never have to use it as a collection), may help with the readability by giving it an actual name instead of a numeric index.
referenced from http://parand.com/say/index.php/2008/10/13/access-python-dictionary-keys-as-properties/
Say you want to access the values if your dictionary via the dot notation instead of the dictionary syntax. That is, you have:
d = {'name':'Joe', 'mood':'grumpy'}
And you want to get at “name” and “mood” via
d.name
d.mood
instead of the usual
d['name']
d['mood']
Why would you want to do this? Maybe you’re fond of the Javascript Way. Or you find it more aesthetic. In my case I need to have the same piece of code deal with items that are either instances of Django models or plain dictionaries, so I need to provide a uniform way of getting at the attributes.
Turns out it’s pretty simple:
class DictObj(object):
def __init__(self, d):
self.d = d
def __getattr__(self, m):
return self.d.get(m, None)
d = DictObj(d)
d.name
# prints Joe
d.mood
# prints grumpy
It seems there are different ways the __repr__ function can return.
I have a class InfoObj that stores a number of things, some of which I don't particularly want users of the class to set by themselves. I recognize nothing is protected in python and they could just dive in and set it anyway, but seems defining it in __init__ makes it more likely someone might see it and assume it's fine to just pass it in.
(Example: Booleans that get set by a validation function when it determines that the object has been fully populated, and values that get calculated from other values when enough information is stored to do so... e.g. A = B + C, so once A and B are set then C is calculated and the object is marked Valid=True.)
So, given all that, which is the best way to design the output of __ repr__?
bob = InfoObj(Name="Bob")
# Populate bob.
# Output type A:
bob.__repr__()
'<InfoObj object at 0x1b91ca42>'
# Output type B:
bob.__repr__()
'InfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'
# Output type C:
bob.__repr__()
'InfoObj.NewInfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'
... the point of type C would be to not happily take all the stuff I'd set 'private' in C++ as arguments to the constructor, and make teammates using the class set it up using the interface functions even if it's more work for them. In that case I would define a constructor that does not take certain things in, and a separate function that's slightly harder to notice, for the purposes of __repr__
If it makes any difference, I am planning to store these python objects in a database using their __repr__ output and retrieve them using eval(), at least unless I come up with a better way. The consequence of a teammate creating a full object manually instead of going through the proper interface functions is just that one type of info retrieval might be unstable until someone figures out what he did.
The __repr__ method is designed to produce the most useful output for the developer, not the enduser, so only you can really answer this question. However, I'd typically go with option B. Option A isn't very useful, and option C is needlessly verbose -- you don't know how your module is imported anyway. Others may prefer option C.
However, if you want to store Python objects is a database, use pickle.
import pickle
bob = InfoObj(Name="Bob")
> pickle.dumps(bob)
b'...some bytestring representation of Bob...'
> pickle.loads(pickle.dumps(bob))
Bob(...)
If you're using older Python (pre-3.x), then note that cPickle is faster, but pickle is more extensible. Pickle will work on some of your classes without any configuration, but for more complicated objects you might want to write custom picklers.
Suppose that I have a class like this
class Employee:
pass
I create two objects for Employee as below
john = Employee()
rob = Employee()
..and create instance variables
john.age = 12
rob.age = '15'
The compiler accepts both and prints the age (john's age in int and rob's age in string). How is this logical? The same data attribute having different type in each object.
Thanks.
Be sure to understand this fundamental principle: in Python, variables don't have types. Values have types. This is the essence of Python's being a dynamically-typed language similarly to Lisp and Javascript, but unlike C, C++ and Java.
>>> foo = 5 # foo now holds a value of type int
>>> foo = 'hello' # foo now holds a value of type string
Here's an excerpt from Wikipedia's entry on typing in Python:
Python uses duck typing and has typed
objects but untyped variable names.
Type constraints are not checked at
compile time; rather, operations on an
object may fail, signifying that the
given object is not of a suitable
type. Despite being dynamically typed,
Python is strongly typed, forbidding
operations that are not well-defined
(for example, adding a number to a
string) rather than silently
attempting to make sense of them.
Do read more on this subject (especially what Duck Typing is) if you want to learn Python.
P.S. This issue is totally orthogonal to attributes of objects. Attributes are just other "variables" in Python, which also can hold values. These values can be of different types.
Because by saying rob.age you are not creating a class-wide data attribute that has a specific type; you are merely creating an instance-local, instance-specific attribute that refers to a concrete entity, the string '15'. To create a class-wide attribute you would have to say Employee.age = … or set age inside the class Employee: block. By setting the attribute to a descriptor, I suppose you could check its type every time it is set and restrict it to an integer or string or whatever; but in general, either a class attribute or an instance attribute is just a name for an object, and all Python cares is that .age names an object.
And note that Python could not really guess what you mean anyway. If you say that john.age is 12, you seem to want Python to guess that all other .age attributes should also be numbers. But why shouldn't Python go even further, and guess that they are integers — or better yet, that they are positive even integers? I really do not think it would be reasonable in any case for Python to extrapolate from a single assignment to some kind of guess as to how you will treat that attribute in all other instances of the class.
It's fundamentally what you get when you have a dynamically typed language.
Type is determined at runtime not at declaration.
It has advantages and disadvantages, but I believe the advantages outweigh its disadvantages in most development contexts.
(It's what Ruby, Python, PHP, etc. do)
Python's compiler does not care what type of value you bind to an attribute/name, nor does it have to; Python's dynamic nature means that the important type checks (which are usually actually attribute checks) are done at runtime.
The term "variable" is confusioning in Python.