Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
On Tue, 17 Dec 2013 08:14:09 +0100, dieter wrote: > Steven D'Aprano writes: > >> On Mon, 16 Dec 2013 12:51:21 +1100, Ben Finney wrote: ... "type(obj)" >> versus "obj.__class__" That is an excellent question, I only wish I had >> an excellent answer to give you. Obviously great minds think alike >> because I was going to ask the same question, prompted by this comment >> from Nick Coghlan on the python-dev list: >> >> "...type(obj).__name__ (working with the concrete type, ignoring any >> proxying) or obj.__class__.__name__ (which takes proxying into >> account)..." >> >> So there is a difference between them, but I'm not entirely sure what >> it is. > > I understand the difference: sometimes you work with proxies (e.g. > "weakref" proxies). A proxie should work mostly like the proxied object > - but in rare cases, you want to detect that what you have is actually a > proxie rather than the real object. You can use "type(obj)" to check the > real type ob "obj" (in some sense, it is more direct - more reliable; > giving you the real type of "obj"). "obj.__class__" on the other hand > uses standard attribute access - and proxying may have customized > attribute access to access the proxied object's attributes rather than > its own: then "obj.__class__" would give you not the type of "obj" (the > proxie) but that of the proxied object. I think I need to see an actual working demonstration, because as far as I can see, type(obj) returns obj.__class__. I'm not suggesting you are wrong, only that code speaks more loudly than words :-) -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
Steven D'Aprano writes: > On Mon, 16 Dec 2013 12:51:21 +1100, Ben Finney wrote: > ... "type(obj)" versus "obj.__class__" > That is an excellent question, I only wish I had an excellent answer to > give you. Obviously great minds think alike because I was going to ask > the same question, prompted by this comment from Nick Coghlan on the > python-dev list: > > "...type(obj).__name__ (working with the concrete type, ignoring any > proxying) or obj.__class__.__name__ (which takes proxying into > account)..." > > So there is a difference between them, but I'm not entirely sure what it > is. I understand the difference: sometimes you work with proxies (e.g. "weakref" proxies). A proxie should work mostly like the proxied object - but in rare cases, you want to detect that what you have is actually a proxie rather than the real object. You can use "type(obj)" to check the real type ob "obj" (in some sense, it is more direct - more reliable; giving you the real type of "obj"). "obj.__class__" on the other hand uses standard attribute access - and proxying may have customized attribute access to access the proxied object's attributes rather than its own: then "obj.__class__" would give you not the type of "obj" (the proxie) but that of the proxied object. -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
On Mon, 16 Dec 2013 12:51:21 +1100, Ben Finney wrote: > Howdy all, > > What is the Pythonic way to determine the type of an object? Are there > multiple valid ways, and when should each be used? That is an excellent question, I only wish I had an excellent answer to give you. Obviously great minds think alike because I was going to ask the same question, prompted by this comment from Nick Coghlan on the python-dev list: "...type(obj).__name__ (working with the concrete type, ignoring any proxying) or obj.__class__.__name__ (which takes proxying into account)..." So there is a difference between them, but I'm not entirely sure what it is. > We have ‘obj.__class__’, an attribute bound to the object's class. Or is > it? When is that true, and when should we not rely on it? I think you can rely on it. I don't believe you can delete the __class__ attribute from an instance: py> class X(object): ... pass ... py> x = X() py> x.__class__ py> del x.__class__ Traceback (most recent call last): File "", line 1, in TypeError: can't delete __class__ attribute I think it is fair to consider __class__ to be part of the "object API" shared by all objects. I suppose it's possible to create a metaclass which does not expose a __class__ attribute, but I would consider that broken by design. Furthermore, you can dynamically set the __class__ of an instance in order to dynamically change its type and therefore behaviour (although there are restrictions on what you can change it to, and from). Using the same x instance as above: py> class Y(object): ... pass ... py> x.__class__ = Y py> type(x) This is by design, and it allows a very useful form of dynamic behaviour: http://code.activestate.com/recipes/68429-ring-buffer/ > We have ‘type(obj)’, calling the constructor for the ‘type’ type in > order to get a reference to the type of ‘obj’. Or is it? When is that > true, and when should we not rely on it? Are there circumstances where type(obj) and obj.__class__ return something different? Based on Nick's comment above, I would have to guess the answer must be yes, but I don't know what those circumstances are. Aside: I'm not sure that it is useful to think of type as the constructor in the one-argument form. If you recall, prior to Python 2.2 `type` was a regular function which took one argument and returned the argument's type: [steve@ando ~]$ python1.5 Python 1.5.2 (#1, Aug 27 2012, 09:09:18) [GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>> type The types returned were very different from the types we know and love since the class/type unification of version 2.2: >>> type(42) >>> int >>> type(42)('2') Traceback (innermost last): File "", line 1, in ? TypeError: call of non-function (type type) So while it is *technically* correct that type(...) calls the type constructor, the one-argument form type(obj) is intended to behave as a function, while the three-argument form type(name, bases, namespace) is intended to behave as a constructor of types. But I digress. > Are there other ways to get at the type of a Python object? What reasons > are there to choose or avoid them? I am not aware of any other ways. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
Chris Angelico writes: > On Mon, Dec 16, 2013 at 3:50 PM, Ben Finney > wrote: > > Should we expect (ignoring pathological cases) the assertion > > ‘type(obj) is obj.__class__’ to hold true? If not, under what > > circumstances would it be sensible for those to differ? > > By "pathological cases", do you mean arbitrarily changing > obj.__class__ By “pathological cases” I mean to acknowledge that, in Python, of course any attribute or function can be changed merely to thwart some rule about how those attributes and functions will generally behave — and to exclude such cases from the question where there is no purpose to the case other than the thwarting of the general rule. -- \ “I still have my Christmas Tree. I looked at it today. Sure | `\ enough, I couldn't see any forests.” —Steven Wright | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
On Sun, Dec 15, 2013 at 8:50 PM, Ben Finney wrote: > Should we expect (ignoring pathological cases) the assertion > ‘type(obj) is obj.__class__’ to hold true? If not, under what > circumstances would it be sensible for those to differ? They differ on old-style classes (in 2.x): the type will be either classobj or instance; and the __class__ doesn't exist (for class objects) or is what you'd expect (for instances). This isn't particularly pathological, so I disagree with the suggestion that one should always definitely use type() for style reasons. -- Devin -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
On Mon, Dec 16, 2013 at 3:50 PM, Ben Finney wrote: > Should we expect (ignoring pathological cases) the assertion > ‘type(obj) is obj.__class__’ to hold true? If not, under what > circumstances would it be sensible for those to differ? By "pathological cases", do you mean arbitrarily changing obj.__class__, or is there some other way for them to differ? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
Ned Batchelder writes: > Generally, my answer would be, "You probably don't need the type as > much as you think you do." > […] > Also, don't overlook isinstance(). Agreed. > But when you do need it, type(x) is better than x.__class__, simply > because we should always favor builtin functions over direct access of > dunder-names where possible. Thanks. Should we expect (ignoring pathological cases) the assertion ‘type(obj) is obj.__class__’ to hold true? If not, under what circumstances would it be sensible for those to differ? -- \ “For fast acting relief, try slowing down.” —Jane Wagner, via | `\ Lily Tomlin | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: Type of an object: ‘obj.__class__’ versus ‘type(obj)’
On 12/15/13 8:51 PM, Ben Finney wrote: Howdy all, What is the Pythonic way to determine the type of an object? Are there multiple valid ways, and when should each be used? We have ‘obj.__class__’, an attribute bound to the object's class. Or is it? When is that true, and when should we not rely on it? We have ‘type(obj)’, calling the constructor for the ‘type’ type in order to get a reference to the type of ‘obj’. Or is it? When is that true, and when should we not rely on it? Are there other ways to get at the type of a Python object? What reasons are there to choose or avoid them? Generally, my answer would be, "You probably don't need the type as much as you think you do." But when you do need it, type(x) is better than x.__class__, simply because we should always favor builtin functions over direct access of dunder-names where possible. Also, don't overlook isinstance(). -- Ned Batchelder, http://nedbatchelder.com -- https://mail.python.org/mailman/listinfo/python-list
Type of an object: ‘obj.__class__’ versus ‘type(obj)’
Howdy all, What is the Pythonic way to determine the type of an object? Are there multiple valid ways, and when should each be used? We have ‘obj.__class__’, an attribute bound to the object's class. Or is it? When is that true, and when should we not rely on it? We have ‘type(obj)’, calling the constructor for the ‘type’ type in order to get a reference to the type of ‘obj’. Or is it? When is that true, and when should we not rely on it? Are there other ways to get at the type of a Python object? What reasons are there to choose or avoid them? -- \ “Pinky, are you pondering what I'm pondering?” “I think so, | `\Brain, but Zero Mostel times anything will still give you Zero | _o__) Mostel.” —_Pinky and The Brain_ | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list