9

Is it possible in python to change what is printed for classes. I know that if we provide __str__ __unicode__ methods, we can change the way instances of a class are printed. But i want to do this for a class

Eg:

class A(object):
    def __str__(self):
        return 'hello'

a = A()
print a

will print hello. Is it possible to change the behaviour of print A which by default prints something like <class '__main__.A'>

Update: I guess i might as well explain the context. I am trying to create MySQL queries and i have classes representing tables. Each of these table-classes have a class variable containing the table name. So what i want to do is to be able to pass the Class as parameter to cursor.execute and have the tablenames substituted in the query.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
z33m
  • 5,993
  • 1
  • 31
  • 42

2 Answers2

7

Yes, by providing a metaclass. This is a bad idea because metaclasses don't compose very well, and it's magical and confusing.

>>> class A(type):
...     def __repr__(self):
...             return '<this is not a class!>'
...
>>> class B(object):
...     __metaclass__ = A
...
>>> print B
<this is not a class!>

(you can change __str__ as well, it depends on the semantics of what this is)


You updated your post to talk about generating SQL queries from a class. Instead of changing str(Class), why not instead use Class.__name__ (i.e. the name you defined it with), or perhaps Class.table_name (i.e. some class attribute you define for each class)? Being able to pass in classes and have them automagically work as table names that aren't of the form <class 'foo.x'> is potentially very confusing to future readers of your code, because it's not clear that this should work from context. The reader must remember that metaclass hacks were involved (a relatively rare thing, although not in ORMs!) and what the metaclass hack did. In contrast, just passing Class.table_name instead of Class makes it very obvious what is going on.

Devin Jeanpierre
  • 92,913
  • 4
  • 55
  • 79
  • "metaclasses don't compose very well, and it's magical and confusing" can you elaborate a little – z33m Apr 14 '11 at 07:18
  • 3
    @zeem Re:composition, using two different metaclasses requires you to create one new metaclass that inherits from both of them, which might not work very well if they aren't meant to be inherited. As a general rule, classes, and especially metaclasses, aren't meant to be multiply inherited from, and this can and will blow up. Re: magical/confusing, the basic problem is that people expects `repr(SomeClass)` to look like the repr of a class, and if you alter it, that breaks this expectation. So people might see a class and not even *know* it's a class. – Devin Jeanpierre Apr 14 '11 at 07:35
4

Easy enough with a metaclass. A metaclass is to the class, what the class is to the instance

class A_meta(type):
    def __str__(cls):
        return 'foobar'


class A(object):
    __metaclass__ = A_meta
    def __str__(self):
        return 'hello'

a = A()
print a
print A
John La Rooy
  • 295,403
  • 53
  • 369
  • 502