When developing code for test automation, I often transform responses from the SUT from XML / JSON / whatever to a Python object model to make working with it afterwards easier.
Since the client should not alter the information stored in the object model, it would make sense to have all instance attributes read-only.
For simple cases, this can be achieved by using a namedtuple from the collections module. But in most cases, a simple namedtuple won't do.
I know that the probably most pythonic way would be to use properties:
class MyReadOnlyClass(object):
def __init__(self, a):
self.__a = a
#property
def a(self):
return self.__a
This is OK if I'm dealing only with a few attributes, but it gets lengthy pretty soon.
So I was wondering if there would be any other acceptable approach? What I came up with was this:
MODE_RO = "ro"
MODE_RW = "rw"
class ReadOnlyBaseClass(object):
__mode = MODE_RW
def __init__(self):
self.__mode = MODE_RO
def __setattr__(self, key, value):
if self.__mode != MODE_RW:
raise AttributeError("May not set attribute")
else:
self.__dict__[key] = value
I could then subclass it and use it like this:
class MyObjectModel(ReadOnlyBaseClass):
def __init__(self, a):
self.a = a
super(MyObjectModel, self).__init__()
After the super call, adding or modifying instance attributes is not possible (... that easily, at least).
A possible caveat I came to think about is that if someone was to modify the __mode attribute and set it to MODE_RO, no new instances could be created. But that seems acceptable since its clearly marked as "private" (in the Pyhon way).
I would be interested if you see any more problems with this solution, or have completely different and better approaches.
Or maybe discourage this at all (with explanation, please)?
Related
The property decorator is a great way to "protect" attributes one wants to set once and never change again. I usually deal with this this way (btw., following a the advice here):
self._name = 'foo'
#property
def name(self):
return self._name
so trying to set name directly yields an AttributeError.
However, I often see the following pattern:
#name.setter
def name(self, value):
self._name = value
#property
def name(self):
return self._name
which seems a little counter-intuitive, as it enables exactly what I want to avoid, and requires extra coding, i.e, theoretically
self.name = 'bar'
would suffice, although it is clear that this would be the worst way to deal with the problem.
The best explanation I can come up with is something like a message from the author saying "you should not change this attribute but if you really want to, there is a mechanism to do it without changing a 'protected' attribute". But then, python doesn't really protect attributes.
So, what's the point, which is more pythonic and why?
You're correct that there's no good reason to use a property if you're not doing anything special in the getter or setter. However, if you do want to do something special (like validate new values, or normalize them in some way), then it makes a lot of sense.
For example, this class's foo attribute will always be clamped between 0 and 1 (and non-numerical values will cause an error immediately):
class Foo:
_foo = 1.0
#foo
def probability(self):
return self._foo
#foo.setter
def foo(self, value):
if value < 0:
value = 0
elif value > 1:
value = 1
self._foo = value
An example with a trivial setter, but a complicated getter might be something like this (deferring an expensive initialization that might not be needed):
class Foo:
_foo = None
def initialize_foo(self):
self._foo = some_expensive_calculation()
#property
def foo(self):
if self._foo is None:
self.initialize_foo() # need the default value
return self._foo
#foo.setter
def foo(self, value):
self._foo = value
If the setter and getter are just directly writing and reading the protected variable, then they're pointless, and using it is not Pythonic; it's just wasting time on property overhead for each access. The attribute should just be made public and the property removed.
The advantage to properties is when you need to replace that simple public attribute with something more powerful, because you can make a property that continues to act like it should for code that was using the attribute, but performs additional work as well. Unless you have additional work though, stick with the attribute if you'd allow it to be written anyway.
Note: Technically, a getter and a setter isn't 100% equivalent to the attribute, since without a deleter, it's not behaviorally identical to the raw attribute. But enforcing non-deletability in your API is silly; developers who go around calling del obj.attr on random attributes of third-party class instances (or almost any instance really) deserve what's coming to them, and you shouldn't be defending against that nonsense at the expense of slowing down and complicating normal use patterns.
I am writing a python class to store data and then another class will create an instance of that class to print different variables. Some class variables require a lot of formatting which may take multiple lines of code to get it in its "final state".
Is it bad practice to just access the variables from outside the class with this structure?
class Data():
def __init__(self):
self.data = "data"
Or is it better practice to use an #property method to access variables?
class Data:
#property
def data(self):
return "data"
Be careful, if you do:
class Data:
#property
def data(self):
return "data"
d = Data()
d.data = "try to modify data"
will give you error:
AttributeError: can't set attribute
And as I see in your question, you want to be able to transform the data until its final state, so, go for the other option
class Data2():
def __init__(self):
self.data = "data"
d2 = Data2()
d2.data = "now I can be modified"
or modify the previus:
class Data:
def __init__(self):
self._data = "data"
#property
def data(self):
return self._data
#data.setter
def data(self, value):
self._data = value
d = Data()
d.data = "now I can be modified"
Common Practice
The normal practice in Python is to exposure the attributes directly. A property can be added later if additional actions are required when getting or setting.
Most of the modules in the standard library follow this practice. Public variables (not prefixed with an underscore) typically don't use property() unless there is a specific reason (such as making an attribute read-only).
Rationale
Normal attribute access (without property) is simple to implement, simple to understand, and runs very fast.
The possibility of use property() afterwards means that we don't have to practice defensive programming. We can avoid having to prematurely implement getters and setters which bloats the code and makes accesses slower.
Basically you could hide lot of complexity in the property and make it look like an attribute. This increases code readability.
Also, you need to understand the difference between property and attribute.
Please refer What's the difference between a Python "property" and "attribute"?
I'm creating several classes to use them as state flags (this is more of an exercise, though I'm going to use them in a real project), just like we use None in Python, i.e.
... some_var is None ...
NoneType has several special properties, most importantly it's a singleton, that is there can't be more than one NoneType instance during any interpreter session, and its instances (None objects) are immutable. I've come up with two possible ways to implement somewhat similar behaviour in pure Python and I'm eager to know which one looks better from the architectural standpoint.
1. Don't use instances at all.
The idea is to have a metaclass, that produces immutable classes. The classes are prohibited to have instances.
class FlagMetaClass(type):
def __setattr__(self, *args, **kwargs):
raise TypeError("{} class is immutable".format(self))
def __delattr__(self, *args, **kwargs):
self.__setattr__()
def __repr__(self):
return self.__name__
class BaseFlag(object):
__metaclass__ = FlagMetaClass
def __init__(self):
raise TypeError("Can't create {} instances".format(type(self)))
def __repr__(self):
return str(type(self))
class SomeFlag(BaseFlag):
pass
And we get the desired behaviour
a = BaseFlag
a is BaseFlag # -> True
a is SomeFlag # -> False
Obviously any attempt to set attributes on these classes will fail (of course there are several hacks to overcome this, but the direct way is closed). And the classes themselves are unique objects loaded in a namespace.
2. A proper singleton class
class FlagMetaClass(type):
_instances = {}
def __call__(cls):
if cls not in cls._instances:
cls._instances[cls] = super(FlagMetaClass, cls).__call__()
return cls._instances[cls] # This may be slightly modified to
# raise an error instead of returning
# the same object, e.g.
# def __call__(cls):
# if cls in cls._instances:
# raise TypeError("Can't have more than one {} instance".format(cls))
# cls._instances[cls] = super(FlagMetaClass, cls).__call__()
# return cls._instances[cls]
def __setattr__(self, *args, **kwargs):
raise TypeError("{} class is immutable".format(self))
def __delattr__(self, *args, **kwargs):
self.__setattr__()
def __repr__(self):
return self.__name__
class BaseFlag(object):
__metaclass__ = FlagMetaClass
__slots__ = []
def __repr__(self):
return str(type(self))
class SomeFlag(BaseFlag):
pass
Here the Flag classes are real singletons. This particular implementation doesn't raise an error when we try to create another instance, but returns the same object (though it's easy to alter this behaviour). Both classes and instances can't be directly modified. The point is to create an instance of each class upon import like it's done with None.
Both approaches give me somewhat immutable unique objects that can be used for comparison just like the None. To me the second one looks more NoneType-like, since None is an instance, but I'm not sure that it's worth the increase in idealogical complexity. Looking forward to hear from you.
Theoretically, it's an interesting exercise. But when you say "though I'm going to use them in a real project" then you lose me.
If the real project is highly unPythonic (using traits or some other package to emulate static typing, using __slots__ to keep people from falling on sharp objects, etc.) -- well, I've got nothing for you, because I've got no use for that, but others do.
If the real project is Pythonic, then do the simplest thing possible.
Your "not use instances at all" answer is the correct one here, but you don't need to do a lot of class definition, either.
For example, if you have a function that could accept None as a real parameter, and you want to tell if the parameter has been defaulted, then just do this:
class NoParameterGiven:
pass
def my_function(my_parameter=NoParameterGiven):
if my_parameter is NoParameterGiven:
<do all my default stuff>
That class is so cheap, there's no reason even to share it between files. Just create it where you need it.
Your state classes are a different story, and you might want to use something like that enum module that #Dunes mentioned -- it has some nice features.
OTOH, if you want to keep it really simple, you could just do something like this:
class MyStates:
class State1: pass
class State2: pass
class State3 pass
You don't need to instantiate anything, and you can refer to them like this: MyStates.State1.
I have class Base. I'd like to extend its functionality in a class Derived. I was planning to write:
class Derived(Base):
def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2):
super().__init__(base_arg1, base_arg2)
# ...
def derived_method1(self):
# ...
Sometimes I already have a Base instance, and I want to create a Derived instance based on it, i.e., a Derived instance that shares the Base object (doesn't re-create it from scratch). I thought I could write a static method to do that:
b = Base(arg1, arg2) # very large object, expensive to create or copy
d = Derived.from_base(b, derived_arg1, derived_arg2) # reuses existing b object
but it seems impossible. Either I'm missing a way to make this work, or (more likely) I'm missing a very big reason why it can't be allowed to work. Can someone explain which one it is?
[Of course, if I used composition rather than inheritance, this would all be easy to do. But I was hoping to avoid the delegation of all the Base methods to Derived through __getattr__.]
Rely on what your Base class is doing with with base_arg1, base_arg2.
class Base(object):
def __init__(self, base_arg1, base_arg2):
self.base_arg1 = base_arg1
self.base_arg2 = base_arg2
...
class Derived(Base):
def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2):
super().__init__(base_arg1, base_arg2)
...
#classmethod
def from_base(cls, b, da1, da2):
return cls(b.base_arg1, b.base_arg2, da1, da2)
The alternative approach to Alexey's answer (my +1) is to pass the base object in the base_arg1 argument and to check, whether it was misused for passing the base object (if it is the instance of the base class). The other agrument can be made technically optional (say None) and checked explicitly when decided inside the code.
The difference is that only the argument type decides what of the two possible ways of creation is to be used. This is neccessary if the creation of the object cannot be explicitly captured in the source code (e.g. some structure contains a mix of argument tuples, some of them with the initial values, some of them with the references to the existing objects. Then you would probably need pass the arguments as the keyword arguments:
d = Derived(b, derived_arg1=derived_arg1, derived_arg2=derived_arg2)
Updated: For the sharing the internal structures with the initial class, it is possible using both approaches. However, you must be aware of the fact, that if one of the objects tries to modify the shared data, the usual funny things can happen.
To be clear here, I'll make an answer with code. pepr talks about this solution, but code is always clearer than English. In this case Base should not be subclassed, but it should be a member of Derived:
class Base(object):
def __init__(self, base_arg1, base_arg2):
self.base_arg1 = base_arg1
self.base_arg2 = base_arg2
class Derived(object):
def __init__(self, base, derived_arg1, derived_arg2):
self.base = base
self.derived_arg1 = derived_arg1
self.derived_arg2 = derived_arg2
def derived_method1(self):
return self.base.base_arg1 * self.derived_arg1
I have a question that is puzzling me recently about which is the best way to retrieve attributes from outside.
Let say I have a class:
class Thing:
def __init__(self, whatever):
self.whatever = whatever
x = Thing('foo')
Now I know that if I want to retrieve whatever attribute I can do this:
x.whatever
I have the habit (probably because I come from other oo languages) to define methods to retrieve class attributes as needed and use them insted of retrieve them directly, like:
class Thing:
def __init__(self, whatever):
self.whatever = whatever
def getWhatever(self):
return self.whatever
In my little experience I've found that using this approach make things easier to mantain in the long term because if I edit the structure of data attributes I have to edit only the specific method.
But since I am not really a python veteran I'd love to know if I am doin' it right or if some other approaches are better and more pythonic. Thoughts?
Defining explicit getters and setters is a bad practice in Python. Instead, use properties:
class Thing(object): # New-style class
def __init__(self, whatever):
self._whatever = whatever
#property
def whatever(self):
return self._whatever # Insert complicated calculation here
So instead of pre-planning by using get methods, just introduce a property when you actually need advanced behavior, and not any earlier.
#phihag has the right idea, and mentions in their answer, but to be more explicit about it: The first step is simply to use the attribute directly:
class Thing(object):
def __init__(self, whatever):
self.whatever = whatever
t = Thing(12)
assert t.whatever == 12
Later, if you find you need to make the whatever attribute more sophisticated, you can turn it into a property:
class Thing(object):
def __init__(self, whatever):
self._whatever = whatever
#property
def whatever(self):
return something_complicated(self._whatever)
t = Thing(12)
assert t.whatever == 12
This way, the calling code doesn't change, and you have a nice clean API to your object.
check python property() http://docs.python.org/library/functions.html#property