From: WANG Cong on 25 Jun 2010 09:15 Hi, list! I have a doubt about the design of dynamic attribute creation by assignments in Python. As we know, in Python, we are able to create a new attribute of a class dynamically by an assignment: >>> class test: pass .... >>> test.a = "hello" >>> test.a 'hello' >>> However, I still don't get the points why Python designs it like this. My points are: 1) Modifying a class attribute is metaprogramming, and this is modifying a class, i.e. adding a new attribute to it, thus this should belong to metaprogramming. (I know, strictly speaking, maybe my definition of "metaprogramming" here is incorrect, I _do_ welcome someone could correct me if I am really wrong, but that is not the main point here, please don't go off-topic.) 2) Metaprogramming should be distinguished with non-meta programming, like templates in C++, it is obvious to see if you are using template metaprogramming in C++. 3) Thus, allowing dynamic attribute creation by assignment _by default_ is not a good design for me. It is not obvious at all to see if I am doing metaprogramming at a first glance. 4) Also, this will _somewhat_ violate the OOP princples, in OOP, this is and should be implemented by inherence. 5) This could hide errors silently, for example, when I do: >>>test.typooooo = "blah" I am expecting Python will compllain that "Hey! You have a typo in the attribute name!". Also, this could make code worse to read, if I add a new attribute in one place, and add another one in the another place, and so on, what attributes the hell do I have finally?! I know someone will say you can change this by overriding the __set_attr__ function, like Recipe 6.3 in Python Cookbook. However, this is not default. In my points of view, a better design should be: 1) Disallow dynamic attribute creations by assignments _by default_, thus I expect an error when I do: >>> foo.new_attr = "blah" AttributeError: by default. 2) For people who want to add a new attribute at runtime, but not to override __set_attr__, he/she should switch to: >>> setattr(foo, "new_attr", "blah") This will be more like doing metaprogramming rather than non-meta programming, at least more obvious than using an assignment. 3) Allow users who don't like this to change by __set_attr__, of course. Someone argued with me that Python is a dynamic language, allowing this is natural. True, I do understand that attributes in Python are stored in an internal dictionary (__dict__), allowing assignments to an non-existing key is natural. However, this will be a little different when we talk about classes attributes, simple assignments could have side-effects, besides the traditional assignments effect, like in C, that is, creating a new attribute silently. So even from a view of beauty, this is not a good design. I hope someone could teach me more about why Python design it like it is. Any reply is more than welcome. Thanks for your time! -- Live like a child, think like the god.
From: Richard Thomas on 25 Jun 2010 09:31 On Jun 25, 2:15 pm, WANG Cong <xiyou.wangc...(a)gmail.com> wrote: > Hi, list! > > I have a doubt about the design of dynamic attribute creation by > assignments in Python. > > As we know, in Python, we are able to create a new attribute of > a class dynamically by an assignment: > > > > >>> class test: pass > ... > >>> test.a = "hello" > >>> test.a > 'hello' > > However, I still don't get the points why Python designs it like this. > > My points are: > > 1) Modifying a class attribute is metaprogramming, and this is modifying > a class, i.e. adding a new attribute to it, thus this should belong > to metaprogramming. (I know, strictly speaking, maybe my definition of > "metaprogramming" here is incorrect, I _do_ welcome someone could > correct me if I am really wrong, but that is not the main point here, > please don't go off-topic.) > > 2) Metaprogramming should be distinguished with non-meta programming, > like templates in C++, it is obvious to see if you are using template > metaprogramming in C++. > > 3) Thus, allowing dynamic attribute creation by assignment _by default_ > is not a good design for me. It is not obvious at all to see if I am > doing metaprogramming at a first glance. > > 4) Also, this will _somewhat_ violate the OOP princples, in OOP, > this is and should be implemented by inherence. > > 5) This could hide errors silently, for example, when I do: > > >>>test.typooooo = "blah" > > I am expecting Python will compllain that "Hey! You have a typo in the > attribute name!". Also, this could make code worse to read, if I > add a new attribute in one place, and add another one in the another > place, and so on, what attributes the hell do I have finally?! > > I know someone will say you can change this by overriding the > __set_attr__ function, like Recipe 6.3 in Python Cookbook. > However, this is not default. In my points of view, a better design > should be: > > 1) Disallow dynamic attribute creations by assignments _by default_, > thus I expect an error when I do: > > >>> foo.new_attr = "blah" > > AttributeError: > > by default. > > 2) For people who want to add a new attribute at runtime, > but not to override __set_attr__, he/she should switch to: > > >>> setattr(foo, "new_attr", "blah") > > This will be more like doing metaprogramming rather than non-meta > programming, at least more obvious than using an assignment. > > 3) Allow users who don't like this to change by __set_attr__, > of course. > > Someone argued with me that Python is a dynamic language, > allowing this is natural. True, I do understand that attributes in > Python are stored in an internal dictionary (__dict__), allowing > assignments to an non-existing key is natural. However, this will be > a little different when we talk about classes attributes, simple > assignments could have side-effects, besides the traditional assignments > effect, like in C, that is, creating a new attribute silently. So even > from a view of beauty, this is not a good design. > > I hope someone could teach me more about why Python design it like > it is. Any reply is more than welcome. > > Thanks for your time! > > -- > Live like a child, think like the god. If you desperately want to limit the attribute assignments that can be performed on an object you can set the __slots__ attribute of its type. However, the Python ethos has always been to restrict as little as necessary to provide the tools it needs. Performing additional checks every time an attribute assignment is performed is completely unnecessary. Remember that unlike C these checks would have to be performed at run-time. Richard.
From: Bruno Desthuilliers on 25 Jun 2010 10:34 WANG Cong a �crit : > Hi, list! > > I have a doubt about the design of dynamic attribute creation by > assignments in Python. > > As we know, in Python, we are able to create a new attribute of > a class dynamically by an assignment: > >>>> class test: pass > ... >>>> test.a = "hello" >>>> test.a > 'hello' > > However, I still don't get the points why Python designs it like this. > > My points are: > (snip) Python's classes are plain objects, and like any other object are created at runtime. Having to special-case them would break the simplicity and uniformity of Python for no good reason. Just like there's no good reason to make setattr() working differently for class and non-class objects. FWIW, what you call "metaprogramming" is just ordinary programming - at least in Python. All your fears and concerns about Python's dynamism are just a priori learned from the "mainstream" B&D culture. From experience, these are non-issues - unless of course misused by some fool, but then there's no way to prevent stupids from doing stupid things. So, yes, Python rely quite a lot on programmer's common sense and discipline. Now the good news is that is JustWork(tm).
From: Steven D'Aprano on 25 Jun 2010 12:25 On Fri, 25 Jun 2010 14:15:12 +0100, WANG Cong wrote: > Hi, list! > > I have a doubt about the design of dynamic attribute creation by > assignments in Python. > > As we know, in Python, we are able to create a new attribute of a class > dynamically by an assignment: > >>>> class test: pass > ... >>>> test.a = "hello" >>>> test.a > 'hello' >>>> >>>> > However, I still don't get the points why Python designs it like this. > > My points are: > > 1) Modifying a class attribute is metaprogramming, and this is modifying > a class, i.e. adding a new attribute to it, thus this should belong to > metaprogramming. Yes, isn't it wonderful? In other languages, metaprogramming is deepest black magic, or even completely impossible. In Python it is so easy that anyone can do it, and it is something beginners learn. > 2) Metaprogramming should be distinguished with non-meta programming, > like templates in C++, it is obvious to see if you are using template > metaprogramming in C++. Why should it be? > 3) Thus, allowing dynamic attribute creation by assignment _by default_ > is not a good design for me. It is not obvious at all to see if I am > doing metaprogramming at a first glance. Why do you care if you are doing metaprogramming? Perhaps other languages make it seem difficult and scary, but in Python it is not. It is simple and easy. > 4) Also, this will _somewhat_ violate the OOP princples, in OOP, this is > and should be implemented by inherence. Perhaps, and perhaps not. But Python has never pretended to slavishly follow OOP "principles". Python does what works, not necessarily what is a "pure" design. Python has functional programming, procedural programming, and OO programming, and happily mixes them all together. > 5) This could hide errors silently, for example, when I do: > >>>>test.typooooo = "blah" Yes, that is one downside to Python's dynamicism. The solutions are: * Unit tests, unit tests, unit tests. Then more unit tests. (You're writing them anyway, aren't you?) * Run PyChecker or PyLint to check the source code for errors. * Don't make typos. *smiles* > I am expecting Python will compllain that "Hey! You have a typo in the > attribute name!". Also, this could make code worse to read, if I add a > new attribute in one place, and add another one in the another place, > and so on, what attributes the hell do I have finally?! Then don't do that. > I know someone will say you can change this by overriding the > __set_attr__ function, like Recipe 6.3 in Python Cookbook. However, this > is not default. In my points of view, a better design should be: > > 1) Disallow dynamic attribute creations by assignments _by default_, There are many languages that do that. Python is not one of them. Python is *designed* to be a dynamic language. If you don't like dynamic languages, then you have many, many, many other choices. Perhaps such a language is better for *you*. Perhaps such non-dynamic languages are better for huge applications written by thousands of developers. But Python is designed to be a rapid prototyping language, and as such, dynamicism is a feature, not a bug. -- Steven
From: WANG Cong on 25 Jun 2010 14:03
On 06/25/10 17:25, Steven D'Aprano <steve(a)REMOVE-THIS-cybersource.com.au> wrote: > On Fri, 25 Jun 2010 14:15:12 +0100, WANG Cong wrote: > >> Hi, list! >> >> I have a doubt about the design of dynamic attribute creation by >> assignments in Python. >> >> As we know, in Python, we are able to create a new attribute of a class >> dynamically by an assignment: >> >>>>> class test: pass >> ... >>>>> test.a = "hello" >>>>> test.a >> 'hello' >>>>> >>>>> >> However, I still don't get the points why Python designs it like this. >> >> My points are: >> >> 1) Modifying a class attribute is metaprogramming, and this is modifying >> a class, i.e. adding a new attribute to it, thus this should belong to >> metaprogramming. > (Thanks for your reply.) > Yes, isn't it wonderful? In other languages, metaprogramming is deepest > black magic, or even completely impossible. In Python it is so easy that > anyone can do it, and it is something beginners learn. > The point is why making metaprogramming easy is wonderful? AND, even if it were wonderful, why only this one, i.e. creating attributes by assignments, not other things? In my points of view, a programming language is wonderful only when it is designed so, there is no other things like this one in Python, AFAIK, are as simple as this one, thus making this one really odd to me. :-) > >> 2) Metaprogramming should be distinguished with non-meta programming, >> like templates in C++, it is obvious to see if you are using template >> metaprogramming in C++. > > Why should it be? It is, if you consider other things of metaprogramming in Python. For example, deleting an attribute. > > >> 3) Thus, allowing dynamic attribute creation by assignment _by default_ >> is not a good design for me. It is not obvious at all to see if I am >> doing metaprogramming at a first glance. > > Why do you care if you are doing metaprogramming? Perhaps other languages > make it seem difficult and scary, but in Python it is not. It is simple > and easy. > I do care, programming for a class is quite different from programming for a non-class, even from a historical reason. They sit in different levels of programming. > >> 4) Also, this will _somewhat_ violate the OOP princples, in OOP, this is >> and should be implemented by inherence. > > Perhaps, and perhaps not. But Python has never pretended to slavishly > follow OOP "principles". Python does what works, not necessarily what is > a "pure" design. Python has functional programming, procedural > programming, and OO programming, and happily mixes them all together. > "Happily mixes them all together" doesn't mean it is elegant. :) > >> 5) This could hide errors silently, for example, when I do: >> >>>>>test.typooooo = "blah" > > Yes, that is one downside to Python's dynamicism. The solutions are: > > * Unit tests, unit tests, unit tests. Then more unit tests. > (You're writing them anyway, aren't you?) > * Run PyChecker or PyLint to check the source code for errors. > * Don't make typos. *smiles* > Well, I am talking in the language design level, if we could solve this problem in the language design level, why do we need to bother these things? > >> I am expecting Python will compllain that "Hey! You have a typo in the >> attribute name!". Also, this could make code worse to read, if I add a >> new attribute in one place, and add another one in the another place, >> and so on, what attributes the hell do I have finally?! > > Then don't do that. > Yeah, "don't do that" is one thing, "Python allows to do that" is another thing. > >> I know someone will say you can change this by overriding the >> __set_attr__ function, like Recipe 6.3 in Python Cookbook. However, this >> is not default. In my points of view, a better design should be: >> >> 1) Disallow dynamic attribute creations by assignments _by default_, > > There are many languages that do that. Python is not one of them. Python > is *designed* to be a dynamic language. If you don't like dynamic > languages, then you have many, many, many other choices. Perhaps such a > language is better for *you*. Perhaps such non-dynamic languages are > better for huge applications written by thousands of developers. But > Python is designed to be a rapid prototyping language, and as such, > dynamicism is a feature, not a bug. Such as? As I said in the previous email, this is not so much related with dynamic programmin or not. Using 'setattr(xxxx)' could also prove Python is a dynamic programming, but Python doesn't choose this by default. Thanks! -- Live like a child, think like the god. |