As others already mentioned, preventing this would require a special case for __init__
, and one of the design principles of Python is to avoid special cases, see the Zen of Python:
Special cases aren't special enough to break the rules.
This design is also in line with other design decisions, e.g, the lack of static type checking or access control modifiers. Python tends to empower its users, not to enforce things.
You can easily prevent this for any particular class by using __slots__
. However, there is no way to change this globally.
While this can in theory cause errors, I wouldn't worry about it much. For example, a typo could mean that you are by accident create a new attribute when you meant to assign to an existing attribute. However, good unit testing coverage will usually catch this.
There are ways, but unless you have at least half a dozen, I'd suggest:
class myclass(object):
def _internal_method(self,a,c,y):
pass # add code here
def method_one(self,a,c): self._internal_method(a,c,"method one")
def method_two(self,a,c): self._internal_method(a,c,"another method")
The other option is to actually really create it dynamically. This can be confusing, because if the object is inspected, the methods aren't there. It looks like this:
class test(object):
def __getattr__(self,attrname):
def _internal_method(a,c):
print "You called %s with %s and %s" % (attrname,a,c)
if attrname in ["method_one","method_two"]:
return _internal_method
else:
raise NameError
a=test()
a.method_one("first","second")
This makes use of the fact that a getting a property (like a method) that does not exist, the object's __getattr__
is called, and the result is passed back. Note that we are passing back the FUNCTION _internal_method
as a.method_one
, not calling it at this stage; that is done after the call to getattr has returned. Think of the last line as being:
tmp=a.method
tmp("first","second")
The first of these calls __getattr__
which returns _internal_method
(but does not call it), the latter calls _internal_method
.
Since _internal_method is declared within __getattr__
, it has the same scope as the call that created it, so self
and attrname
are accessible. Also, _internal_method
is TRULY private, not just "private by convention".
I will reiterate that this is confusing for the next person to maintain your code. For example, if you ask for help(a.method_one)
, you will get the help for _internal_method
instead!
The length of this explanation, and your probable confusing is a very good reason not to use this unless you have to.
Best Answer
One idea off the top of my head would be to create a dictionary holding your classes. This would mean that you can have the instantiation and error handling on very few lines.
I can't really say that it's very clear what's happening, but good naming and a few helpful comments would likely alleviate that; such as calling your dictionary instantiators or something similar. You will also need to collect the classes in some manner.
Here are some other suggestions:
You could potentially use one of the methods mentioned in those answers and wrap it up in a function with a descriptive name.
Having written some dynamic code of similar style in other languages I find that you typically, unsurprisingly, end up with code that is harder to read and much more complex in general. For all its inelegance the if else solution you have is understandable for everyone who knows even a little bit of basic programming.