Structure accessible by attribute name or index options - python

I am very new to Python, and trying to figure out how to create an object that has values that are accessible either by attribute name, or by index. For example, the way os.stat() returns a stat_result or pwd.getpwnam() returns a struct_passwd.
In trying to figure it out, I've only come across C implementations of the above types. Nothing specifically in Python. What is the Python native way to create this kind of object?
I apologize if this has been widely covered already. In searching for an answer, I must be missing some fundamental concept that is excluding me from finding an answer.

Python 2.6 introduced collections.namedtuple to make this easy. With older Python versions you can use the named tuple recipe.
Quoting directly from the docs:
>>> Point = namedtuple('Point', 'x y')
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)

You can't use the same implementation as the result object of os.stat() and others. However Python 2.6 has a new factory function that creates a similar datatype called named tuple. A named tuple is a tuple whose slots can also be addressed by name. The named tuple should not require any more memory, according to the documentation, than a regular tuple, since they don't have a per instance dictionary. The factory function signature is:
collections.namedtuple(typename, field_names[, verbose])
The first argument specifies the name of the new type, the second argument is a string (space or comma separated) containing the field names and, finally, if verbose is true, the factory function will also print the class generated.
Example
Suppose you have a tuple containing a username and password. To access the username you get the item at position zero and the password is accessed at position one:
credential = ('joeuser', 'secret123')
print 'Username:', credential[0]
print 'Password:', credential[1]
There's nothing wrong with this code but the tuple isn't self-documenting. You have to find and read the documentation about the positioning of the fields in the tuple. This is where named tuple can come to the rescue. We can recode the previous example as follows:
import collections
# Create a new sub-tuple named Credential
Credential = collections.namedtuple('Credential', 'username, password')
credential = Credential(username='joeuser', password='secret123')
print 'Username:', credential.username
print 'Password:', credential.password
If you are interested of what the code looks like for the newly created Credential-type you can add verbose=True to the argument list when creating the type, in this particular case we get the following output:
import collections
Credential = collections.namedtuple('Credential', 'username, password', verbose=True)
class Credential(tuple):
'Credential(username, password)'
__slots__ = ()
_fields = ('username', 'password')
def __new__(_cls, username, password):
return _tuple.__new__(_cls, (username, password))
#classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Credential object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
return 'Credential(username=%r, password=%r)' % self
def _asdict(t):
'Return a new dict which maps field names to their values'
return {'username': t[0], 'password': t[1]}
def _replace(_self, **kwds):
'Return a new Credential object replacing specified fields with new values'
result = _self._make(map(kwds.pop, ('username', 'password'), _self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
return tuple(self)
username = _property(_itemgetter(0))
password = _property(_itemgetter(1))
The named tuple doesn't only provide access to fields by name but also contains helper functions such as the _make() function which helps creating an Credential instance from a sequence or iterable. For example:
cred_tuple = ('joeuser', 'secret123')
credential = Credential._make(cred_tuple)
The python library documentation for namedtuple has more information and code examples, so I suggest that you take a peek.

an object that has values that are accessible either by attribute name, or by index
I'm not sure what you're finding hard about this.
A collection accessible by index implements __getitem__.
A collection accessible by names implements __getattr__ (or __getattribute__).
You can implement both without any trouble at all. Or, you can use namedtuple.
To make life simpler, you could extend the tuple class so you don't have to implement your own __getitem__. Or you can define an ordinary class that also has __getitem__ so you didn't have to mess with __getattr__.
For example
>>> class Foo( object ):
... def __init__( self, x, y, z ):
... self.x= x
... self.y= y
... self.z= z
... def __getitem__( self, index ):
... return { 0: self.x, 1: self.y, 2: self.z }[index]
...
>>> f= Foo(1,2,3)
>>> f.x
1
>>> f[0]
1
>>> f[1]
2
>>> f[2]
3
>>> f.y
2

Related

Python-based method for finding an object by name

I'd like some advice on how to better extract objects from the 'self' construct by name such that the object is returned for the string of its type is provided.
My working code is presented below.
def makeObjectTypeList(self):
objectList = []
allObjects = dir( self )
for att in allObjects:
test = getattr(self, att)
test1 = test.__class__.__name__
test2 = len( re.split( self.objectType, test1) )
if test2 > 1:
objectList.append( att)
self.objectList = objectList
The value for self.objectType is the string 'QDial'. And, I return all instances of objects of QDial from the method with the re.split() method and the check on the number of items in its result (e.g., len(re.split()) > 1).
My question is how to make this more compact using 'enumerate', etc. in the mode of Python coding. My code is general so that I can pass it 'QLablel', 'QTabWidget', etc. in self.objectType, and obtain all such type-matched instances. But, it feels clunky, and I don't bother yet to trap for the case of a non-existent class type.
You can use a list comprehension that iterates through the attribute-value pairs of the dict returned by the vars function and retain only those whose class of the value matches self.objectType:
def makeObjectTypeList(self):
self.objectList = [k for k, v in vars(self).items() if v.__class__.__name__ == self.objectType]

Dynamic Object Naming and Class Calling in Python

I'm developing a programming language in Python where you can program a simulation of simple machines. I have written a function that takes some input, parses it, and finds out what the first word is.
Now, for the first word insert, I need to take the next words obj, name, x, and y.
obj: what type of simple machine it is
name: what you want to call the object
x: X coordinate on the graph
y: Y coordinate on the graph
I have already made a function nextword that iterates through the rest of the code and defines each variable as those words, so with the following code:
insert pulley JohnThePulley 3 4
It sees first word is insert, and calls my insert function.
Then, it sets obj to pulley, name to JohnThePulley, and so on.
However, now I need to make an object in the daughter class pulley, under the mother class simple_machines, that has the name JohnThePulley, etc.
The situation I'm in is that for the first word insert, for example, I don't know at all what the next word will be, from all the choices of daughter classes that they can call. I need to create the specified object along with the provided name, the provided X coordinate and the provided Y coordinate.
I have tried doing simple formatting in python using '{}'.format(name) or .format(obj), but those don't work.
# Insert function
def insert(code):
c = 4
syntax = np.array([obj, name, x, y])
nextword(parser.code_array, syntax, c)
objc += 1
return
# Nextword function, code_array[0] is insert, syntax is an array that
# contains all the variables that need to be defined for any function
def nextword(code_array, syntax, c):
assert len(code_array) == c + 1, "Too Many Words!"
for m in range(0, c):
syntax[m] = code_array[m + 1]
return
# Mother Class simple_machines with properties
class simple_machines:
def __init__(self, obj, name, x, y, coords):
self.obj = (
obj
) # what type of obj, in this case, pulley
self.name = name # name, JohnThePulley
self.x = x # 3 in this case
self.y = y # 4 in this case
self.coords = (x, y) # (3,4) in this case
return
# Pulley Class, here so I can later define special properties for a pulley
class pulley(simple_machines):
def __init__(self, name, x, y):
super(simple_machines, self).__init__()
return
# Code that I tried
def insert(code):
c = 4
syntax = np.array([obj, name, x, y])
nextword(parser.code_array, syntax, c)
"{}".format(name) = "{}".format(obj)(
name, x, y
) # this is what my
# instantiation would look like, formatting an object with name, then
# calling a class formatted with obj, and inserting their input of
# name,x,y as the properties
return
I expect an object in pulley to be created with the name JohnThePulley, and the coordinates X = 3 and Y = 4. What I'd like to result in, in simpler terms, is an object called name in a class called obj with the attributes name.x, name.y, etc
However, I get errors like:
NameError: name 'obj' is not defined
or:
SyntaxError: can't assign to function call
The first one apparently means that the word obj isn't being assigned, but the second one apparently means that I can't format a function name or format a variable name and define it as a function (even though I'm instantiating it as a class).
What am I doing wrong? How can I fix this?
name 'obj' is not defined is because obj is defined in another function. You have to use MYOBJECT.obj, not obj alone, and also keep a reference to MYOBJECT.
'{}'.format(obj)(name,x,y) doesn't mean anything, '{}'.format(obj) is a string and isn't callable.
SyntaxError: can't assign to function call is the actual problem you seem to be interested in. You could do globals()['{}'.format(name)] = stuff but it doesn't work for local variables and objects (and your linter is not going to like it).
If you want to do the same for objects you can use setattr(MYOBJECT, '{}'.format(name), '{}'.format(obj))
All of the solutions above are in technical terms considered "ugly" and what you're probably looking for is a dictionary, while it isn't OOP, dictionaries are used behind the scenes to handle exactly what you want to do with objects. An object without methods is essentially a just dictionary.
mydico = dict()
mydico[name] = obj
Also, if name is a string, then '{}'.format(name) is equivalent to name.

Check if object attribute name appears in a string python

I want to:
check whether a string contains an object property
if it does then access the attribute
So for an object of class
class Person(object):
name = ""
age = 0
major = ""
def __init__(self, name="", surname="", father="", age =0):
self.name = name
self.surname = surname
self.father = father
self.age = age
self.identity = name +" "+ surname
def __str__(self):
return self.identity
__repr__ = __str__
and object
person = Person("Earl", "Martin", "Jason", 40)
I would like for string "What is the name"
to return person.name
(I already know which object the string is about)
The most basic solution would be to do cases for each property being there but the actual code has quite a few and I am sure I don't manually have to write them out, I am just new to programming so I am not sure what syntax is used for this
Any help appreciated
You are looking for the function hasattr() and getattr().
To check whether the attribute exists:
hasattr(Person(), 'string')
And to call the attribute:
getattr(Person(), 'string')
As others have noted, getattr is generally useful.
hasattr is of lesser utility; internally, it's basically a getattr call in a try/except AttributeError: block (if AttributeError occurs, it returns False, no exception means True), so if you're considering code like:
if hasattr(myobj, attrname):
attr = getattr(myobj, attrname)
...
just use:
try:
attr = getattr(myobj, attrname)
except AttributeError:
pass
else:
...
to avoid doubling the number of LEGB lookups, function calls and attribute lookups.
Alternatively, for repeatedly pulling named attribute(s), operator.attrgetter basically lets you make an optimized version of getattr that pre-binds the attribute name to lookup (making it ideal for use with stuff like the map and filter functions, as it makes them more efficient than their equivalent listcomps/genexprs).
On top of those, depending on what your goal is, the dir and (slightly less reliably, due to issues with classes that use __slots__ to define a known set of variables to reduce memory usage and prevent auto-vivification) vars functions may be useful.
For example, in your example case of pulling any attributes corresponding to a word from a string, you could do a bulk identification of legal attribute names using vars()/dir() and your choice of filter or set operations (or a mix) depending on the importance of order, uniqueness, etc.:
from future_builtins import filter # Only on Py2, not Py3
import operator
import re
def query_obj(obj, querystr):
# Extract list of legal attribute names from string
words = re.findall(r'\w+', querystr)
# Reduce to names present on object's __dict__; no need to construct temporaries
attrnames = filter(vars(obj).__contains__, words)
# Alternate if __slots__ might be an issue (temp list & frozenset):
attrnames = filter(frozenset(dir(obj)).__contains__, words)
# Or combine the two to be sure (on Py3, use .keys() instead of .viewkeys())
# (temp list and set):
attrnames = filter((vars(obj).viewkeys() | dir(obj)).__contains__, words)
# Convenient way to get all names discovered at once; returns single object
# for single attr, tuple of objects for multiple attrs:
return operator.attrgetter(*attrnames)(obj)
# If you want a tuple unconditionally, use this instead:
return tuple(getattr(obj, name) for name in attrnames)
# Or to only return the first attribute encountered, raising StopIteration
# if no attributes are found:
return next(getattr(obj, name) for name in attrnames)
Then usage is:
>>> person = Person("Earl", "Martin", "Jason", 40)
>>> query_obj(person, "What is the name?")
'Earl' # Would be ('Earl',) in unconditional tuple case
>>> query_obj(person, "What is the name and surname?")
('Earl', 'Martin') # Would be 'Earl' in single return case

What do I do when I need a self referential dictionary?

I'm new to Python, and am sort of surprised I cannot do this.
dictionary = {
'a' : '123',
'b' : dictionary['a'] + '456'
}
I'm wondering what the Pythonic way to correctly do this in my script, because I feel like I'm not the only one that has tried to do this.
EDIT: Enough people were wondering what I'm doing with this, so here are more details for my use cases. Lets say I want to keep dictionary objects to hold file system paths. The paths are relative to other values in the dictionary. For example, this is what one of my dictionaries may look like.
dictionary = {
'user': 'sholsapp',
'home': '/home/' + dictionary['user']
}
It is important that at any point in time I may change dictionary['user'] and have all of the dictionaries values reflect the change. Again, this is an example of what I'm using it for, so I hope that it conveys my goal.
From my own research I think I will need to implement a class to do this.
No fear of creating new classes -
You can take advantage of Python's string formating capabilities
and simply do:
class MyDict(dict):
def __getitem__(self, item):
return dict.__getitem__(self, item) % self
dictionary = MyDict({
'user' : 'gnucom',
'home' : '/home/%(user)s',
'bin' : '%(home)s/bin'
})
print dictionary["home"]
print dictionary["bin"]
Nearest I came up without doing object:
dictionary = {
'user' : 'gnucom',
'home' : lambda:'/home/'+dictionary['user']
}
print dictionary['home']()
dictionary['user']='tony'
print dictionary['home']()
>>> dictionary = {
... 'a':'123'
... }
>>> dictionary['b'] = dictionary['a'] + '456'
>>> dictionary
{'a': '123', 'b': '123456'}
It works fine but when you're trying to use dictionary it hasn't been defined yet (because it has to evaluate that literal dictionary first).
But be careful because this assigns to the key of 'b' the value referenced by the key of 'a' at the time of assignment and is not going to do the lookup every time. If that is what you are looking for, it's possible but with more work.
What you're describing in your edit is how an INI config file works. Python does have a built in library called ConfigParser which should work for what you're describing.
This is an interesting problem. It seems like Greg has a good solution. But that's no fun ;)
jsbueno as a very elegant solution but that only applies to strings (as you requested).
The trick to a 'general' self referential dictionary is to use a surrogate object. It takes a few (understatement) lines of code to pull off, but the usage is about what you want:
S = SurrogateDict(AdditionSurrogateDictEntry)
d = S.resolve({'user': 'gnucom',
'home': '/home/' + S['user'],
'config': [S['home'] + '/.emacs', S['home'] + '/.bashrc']})
The code to make that happen is not nearly so short. It lives in three classes:
import abc
class SurrogateDictEntry(object):
__metaclass__ = abc.ABCMeta
def __init__(self, key):
"""record the key on the real dictionary that this will resolve to a
value for
"""
self.key = key
def resolve(self, d):
""" return the actual value"""
if hasattr(self, 'op'):
# any operation done on self will store it's name in self.op.
# if this is set, resolve it by calling the appropriate method
# now that we can get self.value out of d
self.value = d[self.key]
return getattr(self, self.op + 'resolve__')()
else:
return d[self.key]
#staticmethod
def make_op(opname):
"""A convience class. This will be the form of all op hooks for subclasses
The actual logic for the op is in __op__resolve__ (e.g. __add__resolve__)
"""
def op(self, other):
self.stored_value = other
self.op = opname
return self
op.__name__ = opname
return op
Next, comes the concrete class. simple enough.
class AdditionSurrogateDictEntry(SurrogateDictEntry):
__add__ = SurrogateDictEntry.make_op('__add__')
__radd__ = SurrogateDictEntry.make_op('__radd__')
def __add__resolve__(self):
return self.value + self.stored_value
def __radd__resolve__(self):
return self.stored_value + self.value
Here's the final class
class SurrogateDict(object):
def __init__(self, EntryClass):
self.EntryClass = EntryClass
def __getitem__(self, key):
"""record the key and return"""
return self.EntryClass(key)
#staticmethod
def resolve(d):
"""I eat generators resolve self references"""
stack = [d]
while stack:
cur = stack.pop()
# This just tries to set it to an appropriate iterable
it = xrange(len(cur)) if not hasattr(cur, 'keys') else cur.keys()
for key in it:
# sorry for being a duche. Just register your class with
# SurrogateDictEntry and you can pass whatever.
while isinstance(cur[key], SurrogateDictEntry):
cur[key] = cur[key].resolve(d)
# I'm just going to check for iter but you can add other
# checks here for items that we should loop over.
if hasattr(cur[key], '__iter__'):
stack.append(cur[key])
return d
In response to gnucoms's question about why I named the classes the way that I did.
The word surrogate is generally associated with standing in for something else so it seemed appropriate because that's what the SurrogateDict class does: an instance replaces the 'self' references in a dictionary literal. That being said, (other than just being straight up stupid sometimes) naming is probably one of the hardest things for me about coding. If you (or anyone else) can suggest a better name, I'm all ears.
I'll provide a brief explanation. Throughout S refers to an instance of SurrogateDict and d is the real dictionary.
A reference S[key] triggers S.__getitem__ and SurrogateDictEntry(key) to be placed in the d.
When S[key] = SurrogateDictEntry(key) is constructed, it stores key. This will be the key into d for the value that this entry of SurrogateDictEntry is acting as a surrogate for.
After S[key] is returned, it is either entered into the d, or has some operation(s) performed on it. If an operation is performed on it, it triggers the relative __op__ method which simple stores the value that the operation is performed on and the name of the operation and then returns itself. We can't actually resolve the operation because d hasn't been constructed yet.
After d is constructed, it is passed to S.resolve. This method loops through d finding any instances of SurrogateDictEntry and replacing them with the result of calling the resolve method on the instance.
The SurrogateDictEntry.resolve method receives the now constructed d as an argument and can use the value of key that it stored at construction time to get the value that it is acting as a surrogate for. If an operation was performed on it after creation, the op attribute will have been set with the name of the operation that was performed. If the class has a __op__ method, then it has a __op__resolve__ method with the actual logic that would normally be in the __op__ method. So now we have the logic (self.op__resolve) and all necessary values (self.value, self.stored_value) to finally get the real value of d[key]. So we return that which step 4 places in the dictionary.
finally the SurrogateDict.resolve method returns d with all references resolved.
That'a a rough sketch. If you have any more questions, feel free to ask.
If you, just like me wandering how to make #jsbueno snippet work with {} style substitutions, below is the example code (which is probably not much efficient though):
import string
class MyDict(dict):
def __init__(self, *args, **kw):
super(MyDict,self).__init__(*args, **kw)
self.itemlist = super(MyDict,self).keys()
self.fmt = string.Formatter()
def __getitem__(self, item):
return self.fmt.vformat(dict.__getitem__(self, item), {}, self)
xs = MyDict({
'user' : 'gnucom',
'home' : '/home/{user}',
'bin' : '{home}/bin'
})
>>> xs["home"]
'/home/gnucom'
>>> xs["bin"]
'/home/gnucom/bin'
I tried to make it work with the simple replacement of % self with .format(**self) but it turns out it wouldn't work for nested expressions (like 'bin' in above listing, which references 'home', which has it's own reference to 'user') because of the evaluation order (** expansion is done before actual format call and it's not delayed like in original % version).
Write a class, maybe something with properties:
class PathInfo(object):
def __init__(self, user):
self.user = user
#property
def home(self):
return '/home/' + self.user
p = PathInfo('thc')
print p.home # /home/thc
As sort of an extended version of #Tony's answer, you could build a dictionary subclass that calls its values if they are callables:
class CallingDict(dict):
"""Returns the result rather than the value of referenced callables.
>>> cd = CallingDict({1: "One", 2: "Two", 'fsh': "Fish",
... "rhyme": lambda d: ' '.join((d[1], d['fsh'],
... d[2], d['fsh']))})
>>> cd["rhyme"]
'One Fish Two Fish'
>>> cd[1] = 'Red'
>>> cd[2] = 'Blue'
>>> cd["rhyme"]
'Red Fish Blue Fish'
"""
def __getitem__(self, item):
it = super(CallingDict, self).__getitem__(item)
if callable(it):
return it(self)
else:
return it
Of course this would only be usable if you're not actually going to store callables as values. If you need to be able to do that, you could wrap the lambda declaration in a function that adds some attribute to the resulting lambda, and check for it in CallingDict.__getitem__, but at that point it's getting complex, and long-winded, enough that it might just be easier to use a class for your data in the first place.
This is very easy in a lazily evaluated language (haskell).
Since Python is strictly evaluated, we can do a little trick to turn things lazy:
Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
d1 = lambda self: lambda: {
'a': lambda: 3,
'b': lambda: self()['a']()
}
# fix the d1, and evaluate it
d2 = Y(d1)()
# to get a
d2['a']() # 3
# to get b
d2['b']() # 3
Syntax wise this is not very nice. That's because of us needing to explicitly construct lazy expressions with lambda: ... and explicitly evaluate lazy expression with ...(). It's the opposite problem in lazy languages needing strictness annotations, here in Python we end up needing lazy annotations.
I think with some more meta-programmming and some more tricks, the above could be made more easy to use.
Note that this is basically how let-rec works in some functional languages.
The jsbueno answer in Python 3 :
class MyDict(dict):
def __getitem__(self, item):
return dict.__getitem__(self, item).format(self)
dictionary = MyDict({
'user' : 'gnucom',
'home' : '/home/{0[user]}',
'bin' : '{0[home]}/bin'
})
print(dictionary["home"])
print(dictionary["bin"])
Her ewe use the python 3 string formatting with curly braces {} and the .format() method.
Documentation : https://docs.python.org/3/library/string.html

Are object literals Pythonic?

JavaScript has object literals, e.g.
var p = {
name: "John Smith",
age: 23
}
and .NET has anonymous types, e.g.
var p = new { Name = "John Smith", Age = 23}; // C#
Something similar can be emulated in Python by (ab)using named arguments:
class literal(object):
def __init__(self, **kwargs):
for (k,v) in kwargs.iteritems():
self.__setattr__(k, v)
def __repr__(self):
return 'literal(%s)' % ', '.join('%s = %r' % i for i in sorted(self.__dict__.iteritems()))
def __str__(self):
return repr(self)
Usage:
p = literal(name = "John Smith", age = 23)
print p # prints: literal(age = 23, name = 'John Smith')
print p.name # prints: John Smith
But is this kind of code considered to be Pythonic?
Why not just use a dictionary?
p = {'name': 'John Smith', 'age': 23}
print p
print p['name']
print p['age']
Have you considered using a named tuple?
Using your dict notation
>>> from collections import namedtuple
>>> L = namedtuple('literal', 'name age')(**{'name': 'John Smith', 'age': 23})
or keyword arguments
>>> L = namedtuple('literal', 'name age')(name='John Smith', age=23)
>>> L
literal(name='John Smith', age=23)
>>> L.name
'John Smith'
>>> L.age
23
It is possible to wrap this behaviour into a function easily enough
def literal(**kw):
return namedtuple('literal', kw)(**kw)
the lambda equivalent would be
literal = lambda **kw: namedtuple('literal', kw)(**kw)
but personally I think it's silly giving names to "anonymous" functions
From ActiveState:
class Bunch:
def __init__(self, **kwds):
self.__dict__.update(kwds)
# that's it! Now, you can create a Bunch
# whenever you want to group a few variables:
point = Bunch(datum=y, squared=y*y, coord=x)
# and of course you can read/write the named
# attributes you just created, add others, del
# some of them, etc, etc:
if point.squared > threshold:
point.isok = 1
I don't see anything wrong with creating "anonymous" classes/instances. It's often very convienient to create one with simple function call in one line of code. I personally use something like this:
def make_class( *args, **attributes ):
"""With fixed inability of using 'name' and 'bases' attributes ;)"""
if len(args) == 2:
name, bases = args
elif len(args) == 1:
name, bases = args[0], (object, )
elif not args:
name, bases = "AnonymousClass", (object, )
return type( name, bases, attributes )
obj = make_class( something = "some value" )()
print obj.something
For creating dummy objects it works just fine. Namedtuple is ok, but is immutable, which can be inconvenient at times. And dictionary is... well, a dictionary, but there are situations when you have to pass something with __getattr__ defined, instead of __getitem__.
I don't know whether it's pythonic or not, but it sometimes speeds things up and for me it's good enough reason to use it (sometimes).
I'd say that the solution you implemented looks pretty Pythonic; that being said, types.SimpleNamespace (documented here) already wraps this functionality:
from types import SimpleNamespace
p = SimpleNamespace(name = "John Smith", age = 23)
print(p)
From the Python IAQ:
As of Python 2.3 you can use the syntax
dict(a=1, b=2, c=3, dee=4)
which is good enough as far as I'm concerned. Before Python 2.3 I used the one-line function
def Dict(**dict): return dict
I think object literals make sense in JavaScript for two reasons:
In JavaScript, objects are only way to create a “thing” with string-index properties. In Python, as noted in another answer, the dictionary type does that.
JavaScript‘s object system is prototype-based. There’s no such thing as a class in JavaScript (although it‘s coming in a future version) — objects have prototype objects instead of classes. Thus it’s natural to create an object “from nothing”, via a literal, because all objects only require the built-in root object as a prototype. In Python, every object has a class — you’re sort of expected to use objects for things where you’d have multiple instances, rather than just for one-offs.
Thus no, object literals aren’t Pythonic, but they are JavaScripthonic.
A simple dictionary should be enough for most cases.
If you are looking for a similar API to the one you indicated for the literal case, you can still use dictionaries and simply override the special __getattr__ function:
class CustomDict(dict):
def __getattr__(self, name):
return self[name]
p = CustomDict(user='James', location='Earth')
print p.user
print p.location
Note: Keep in mind though that contrary to namedtuples, fields are not validated and you are in charge of making sure your arguments are sane. Arguments such as p['def'] = 'something' are tolerated inside a dictionary but you will not be able to access them via p.def.

Categories

Resources