On 20 December 2010 10:08, Steven D'Aprano <steve@pearwood.info> wrote:
Michael wrote:

On 19 Dec 2010, at 21:26, Steven D'Aprano <steve@pearwood.info> wrote:

Eike Welk wrote:

My positive attitude towards this syntax comes from the only weakness that Python IMHO has: You can't easily see which data attributes an instance has.
What's wrong with dir(obj) and vars(obj)?
[...]

I think the issue that Elke is pointing out is that dir(Spam) knows nothing about y (whereas it would if you used __slots__).

Then he should have said -- he explicitly said:

"You can't easily see which data attributes an INSTANCE has."
[emphasis added]

Well sure - just by looking at the class you can't tell what members an INSTANCE has... :-)

 

As a general rule, you can't expect the class to know what attributes an instance has. This is a deliberate design choice. If you want to find out what attributes an object has, you ask the object, not the object's parent class.

Think of this as a variation on the Law of Demeter: if you want to know how many fleas a dog has, inspect the dog, not the dog's owner.



One answer is to have class member defaults for all instance members.

Well, that's an answer, but I'm not sure what the question is. From time to time I create a class which includes default class attributes, which then get optionally overridden by instance attributes. But that's much rarer than the usual case, where the instance has the attributes and the class doesn't.

I would find it very disturbing to see classes declare meaningless class attributes (probably set to None) just to make it easier to predict what attributes the instances will get. That's pretty close to this horror:
[snip...]

Personally, I've never found this to be a problem in practice.

The only place I've found it relevant is when mocking out objects that you don't want instantiated in your test. mock.Mock (and mock.patch) can create mock objects that behave like the original (in terms of available methods and members) if you pass it a reference to the object it is mocking. If member creation is 'hidden' inside __init__ then Mock can't know what members are available.



 
If I want to find out what attributes an instance of a class will have, I instantiate the class and inspect the instance. Or I read the docs. Looking at the source code is also an option (if the source code is available). For most classes, any attributes will be set in the __init__ method. If you have to read the source to determine what attributes exist, there's not much difference between:

Well, if there's anything you *can't* tell about the behaviour of objects by reading the source code then something odd is going on. ;-)

Programmatic inspection is where it is relevant (to me at least).

Michael


 

class Spam:
   a = 1
   b = 2
   c = 3

and

class Spam:
   def __init(self):
       self.a = 1
       self.b = 2
       self.c = 3


But normally I just care about methods, not data attributes, and for that dir(cls) is perfectly adequate. (There may be the odd object that includes instance methods, but they'll be rare.)




--
Steven
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
http://mail.python.org/mailman/listinfo/python-ideas



--
http://www.voidspace.org.uk/

May you do good and not evil
May you find forgiveness for yourself and forgive others
May you share freely, never taking more than you give.
-- the sqlite blessing http://www.sqlite.org/different.html