How can I add this metaclass to *all* classes in the system?
(In ruby I would alter the "Class" class)
.
This is a terrible idea. When my, Joe Modulewriter, released my
library of AwesomeCoolClasses, i except my metaclass to be something
particular and if it starts getting wonky and I do anything hackery on
my end with the types, then the end-user's computer might 'splode!
What I am trying to say, is its a terrible idea to go changing other
peoples' classes at runtime without knowing the real affects of what
is going on. If you are just going to shoot yourself in the foot, why
should we even give you a gun?
You'd have to set
__metaclass__ = whatever
at the top of each module whose classes are to get the new behavior.
You can't alter classes which you don't control or create in your code.
Georg
I think '__metaclass__ = whatever' affects only the creation of classes that
would otherwise be old-style classes?
> You can't alter classes which you don't control or create in your code.
I remeber I've seen an implementation of import_with_metaclass somewhere on
IBM's developerworks. I didn't quite undersntad it though.
--
damjan
It seems so:
http://mail.python.org/pipermail/python-list/2003-June/166572.html
> > You can't alter classes which you don't control or create in your code.
>
> I remeber I've seen an implementation of import_with_metaclass somewhere on
> IBM's developerworks. I didn't quite undersntad it though.
http://www-128.ibm.com/developerworks/linux/library/l-pymeta.html
I am not so much interested in old-style, as is start production with
python 2.4 (possibly even with python 2.5).
.
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden
Reminds me of when I was learning Smalltalk, and modified printOn (ST's
equivalent of str()) of the root-of-all-classes object class. I don't
remember the exact error I made, but it was a mess undoing it!
-- Paul
...except in C.
I assume the "root class" should be available/changeable in "C", too.
Do I have to change the sources directly, or does python provide
"C-level-extension/modication" mechanisms, which can be applied to
core-level classes, too?
Is the Python Object Model documented anywhere in a diagram, something
similar to this?:
http://case.lazaridis.com/wiki/RubyObjectModel
.
What could you possibly want to do this for so badly that you would
shun all alternatives and even resort to hacking up the runtime at the
C-level to redefine core types in non-standard and unpredictable
ways?! Seriously, please give a good reason for every doing this. I
can't imagine there is any way it would justify all this in the face
of just looking for an alternative. You aren't trying to use python,
at this point, you are trying to fork it.
Wrong.
If you set __metaclass__ = type, every class in that module will be new-style.
If you set __metaclass__ = MyClass, and MyClass inherits from <type>, every
class in that module will be new-style and have MyClass as a metaclass.
The usual way to create new-style classes, inheriting from object or another
new-style class, works because if no __metaclass__ is defined, the first
base class's class is taken as the metaclass.
Georg
I was under that impression, too. But this behaves different (py2.4):
---- test.py ----
class meta(type):
def __new__(*args):
print args
return type(*args[1:])
__metaclass__ = meta
class OldStyle:
pass
class NewStyle(object):
#__metaclass__ = meta
pass
---- test.py ----
deets$ python2.4 /tmp/test.py
(<class '__main__.meta'>, 'OldStyle', (), {'__module__': '__main__'})
deets$
I was astonished to see that. Any explanation?
Diez
>>> from UserDict import UserDict
>>> type(UserDict)
<type 'classobj'>
>>> class A(UserDict):
... pass
>>> type(A)
<type 'classobj'>
>>> __metaclass__ = type
>>> class B(UserDict):
... pass
>>> type(B)
<type 'classobj'>
It seems that NOT every class in my module will be a new style class,
especially those that inherit from other old-style classes in other
modules.
--
damjan
[...]
> deets$ python2.4 /tmp/test.py
> (<class '__main__.meta'>, 'OldStyle', (), {'__module__': '__main__'})
> deets$
>
> I was astonished to see that. Any explanation?
Yes. I was wrong, the order of lookup is reversed. This first base class's
class is used before the global __metaclass__.
So what Damjan said is correct: global __metaclass__ is only usable for
classes that don't have bases.
Whether this is desirable is another question...
Georg
I got confused from the discussion about __metaclass__.
possibly a little more practical.
I like to add a method "writeDebug(self, msg)" to all (or the most
possible) classes in the system.
How do I do this?
* with new style classes
* with old style classes
> .
>
> http://lazaridis.com
OMFG. For asking the question (paraphrased) "why do you want to do this",
Mr. Spealman received an
http://case.lazaridis.com/wiki/Please#OffTopicPosts
But now you do exactly that - give more details. Maybe this could teach you
the lesson that the variance of input you get here to your questions is
worth considering?
But I've got the wicked feeling that this won't happen...
Diez
It's easy:
def writeDebug(msg):
print "I do not debug things, I _evaluate_ with professionals on the
industries! See ticket 547!\n" \
"Oh yeah, and %s" % msg
...
class Foo:
writeDebug("how can I configure the interpreter for understand
Klingon participals and noun-phrases? Must I rectify the standard
dictionaries first?")
Regards,
Jordan
I've not given more details, but less.
Just simplified my request.
.
where do I place this function...
> ...
> class Foo:
> writeDebug("how can I configure the interpreter for understand
> Klingon participals and noun-phrases? Must I rectify the standard
> dictionaries first?")
...thus it becomes available within class "Foo" and all other Classes?
Something like a central import?
.
The place where you want it to be.
> ...thus it becomes available within class "Foo" and all other Classes?
Anything defined in the top-level (i.e., the sys.modules['__main__']
namespace) is accessible in every scope...but I assume you already know
that.
You could also use a super-duper super class from which to derive all
your other classes, and add/replace any methods you want there:
class lazaridis(object):
def evaluate(self, community):
if 1 is 1:
print "Evaluating %s... Result: failed!" % community
class Foo(lazaridis, str):
pass
f=Foo('This has been a test of the lazaridis evaluation system')
f.evaluate('Python')
f.evaluate('Ruby')
f.evaluate('Java')
print f
> Something like a central import?
That would probably be the most logical thing to do.
But again, I assume you already know all this, so why are you asking?
Is this part of the evaluation process?
Regards,
Jordan
> I like to add a method "writeDebug(self, msg)" to all (or the most
> possible) classes in the system.
>
> How do I do this?
>
> * with new style classes
> * with old style classes
Short answer: you can't do it for builtin or extension types:
>>> list.writeDebug = lambda msg: "You'd wish"
...
TypeError: can't set attributes of built-in/extension type 'list'
Longer asnwer: Make it a function instead of a method. This function
could try to call the respective method, and as a fallback it would
have hardcoded what to do for each supported class, something like:
def writeDebug(obj, msg):
try: return obj.writeDebug(msg)
except AttributeError:
if isinstance(obj,list):
# list msg
elif isinstance(obj,tuple):
# tuple msg
...
else:
# default object msg
If you insist though that you'd rather not use functions but only
methods, tough luck; you're better off with Ruby.
George
no, I don't know it.
how do I define something into the top-level namespace? I assume I
could place it into the root-package of my project, into the __init__
function.
But how do I place it within my computers python installation (the big
init)?
> You could also use a super-duper super class from which to derive all
> your other classes, and add/replace any methods you want there:
>
> class lazaridis(object):
...
I am aware of this technique.
But I want to modify existent classes, without touching their code.
> > Something like a central import?
>
> That would probably be the most logical thing to do.
>
> But again, I assume you already know all this, so why are you asking?
> Is this part of the evaluation process?
I am not evaluating Python, I've started using it:
http://case.lazaridis.com/wiki/Lang
http://dev.lazaridis.com/base
-
I've noticed some interesting code on you website:
"
class file(file):
def reopen(self, name=None, mode='w', bufsize=None):
...
fh = file('test.txt', 'rb')
print fh # <open file 'test.txt', mode 'rb' at 0xb7c92814>
fh.reopen(mode='wb')
"
http://rightfootin.blogspot.com/2006/09/ruby-reopen.html
does this mean that I can add a method to a class in a similar way with
ruby? (by using class class-name(class-name): )
but the limitation is that I cannot do this with the python build-in
types?:
http://rightfootin.blogspot.com/2006/08/of-rocks-and-reptiles.html
.
OK...so how do you evaluate a language when you don't know its basic
operations? Hmmm, sounds fishy.
> how do I define something into the top-level namespace? I assume I
> could place it into the root-package of my project, into the __init__
> function.
>
> But how do I place it within my computers python installation (the big
> init)?
When you just say:
def blah(): pass
Now 'blah' function is in the top-level namespace, just like global
variables. Or if it's in a different file, you'd say 'from blah import
*'. You honestly don't know this?!??
> I am aware of this technique.
>
> But I want to modify existent classes, without touching their code.
The only way to do this is to explicitly subclass the existent classes
with your own class and modify what you want there in your subclass
(see below), or use multiple inheritence as I suggested previously.
> I've noticed some interesting code on you website:
>
> "
> class file(file):
> def reopen(self, name=None, mode='w', bufsize=None):
> ...
>
> fh = file('test.txt', 'rb')
> print fh # <open file 'test.txt', mode 'rb' at 0xb7c92814>
> fh.reopen(mode='wb')
> "
> http://rightfootin.blogspot.com/2006/09/ruby-reopen.html
>
> does this mean that I can add a method to a class in a similar way with
> ruby? (by using class class-name(class-name): )
Basically, yes. In ruby you can reopen base classes; in python you can
get the same effect by subclassing the base classes with the same name
as the base class, then instantiating all your objects as that class.
This is the exact same idea as a "super-duper super class" as I
mentioned above.
> but the limitation is that I cannot do this with the python build-in
> types?:
>
> http://rightfootin.blogspot.com/2006/08/of-rocks-and-reptiles.html
You can subclass buit-in types using the same name as the parent class.
In fact here is what I use:
## my little library to make python more OO
## i.e., to get rid of the top-level junk...
## or at least to hide it behind some pretty
## object attributes :)
##
## YMMV - and don't complain if you don't
## like it; I wrote it for ME, not you
##
## Jordan Callicoat < Monke...@gmail.com >
## some global methods so we can use them
## to set up the class methods
def rpr(self):
return str(repr(self))
def stri(self):
return str(self)
def inte(self):
return int(self)
def leng(self):
return int(len(self))
def say(self):
print(self)
return self
def joi(self, sep=''):
return str(sep.join(self))
def ma(self, m):
return list(map(m, self))
def filt(self, m):
return list(filter(m, self))
def redu(self, m):
return list(reduce(m, self))
## now build all the subclasses
class int(int):
"""
Wrapper class for +int+
Provided methods:
str(), int(), repr(), say(),
len(), plus(), minus(),
times(), divided_by()
"""
def plus(self, i):
return int(self + i)
def minus(self, i):
return int(self - i)
def times(self, i):
return int(self * i)
def divided_by(self, i):
return int(self / i)
int.str = stri
int.repr = rpr
int.len = leng
int.int = inte
int.say = say
class str(str):
"""
Wrapper class for +str+
Provided methods:
str(), int(), repr(), say(),
len(), plus(), times()
"""
def plus(self, s):
return str(self + s)
def times(self, i):
return str(self * i)
str.str = stri
str.repr = rpr
str.len = leng
str.int = inte
str.say = say
class list(list):
"""
Wrapper class for +list+
Provided methods:
str(), int(), repr(), say(),
len(), plus(), times(), join()
"""
def plus(self, l):
return list(self + l)
def times(self, i):
return list(self * i)
list.str = stri
list.repr = rpr
list.len = leng
list.say = say
list.join = joi
list.map = ma
list.filter = filt
list.reduce = redu
class tuple(tuple):
"""
Wrapper class for +tuple+
Provided methods:
str(), int(), repr(), say(),
len(), plus(), times(), join()
"""
def plus(self, l):
return tuple(self + l)
def times(self, i):
return tuple(self * i)
tuple.str = stri
tuple.repr = rpr
tuple.len = leng
tuple.say = say
tuple.join = joi
tuple.map = ma
tuple.filter = filt
tuple.reduce = redu
class dict(dict):
"""
Wrapper class for +dict+
Provided methods:
str(), int(), repr(), say(),
len()
"""
pass
dict.str = stri
dict.repr = rpr
dict.len = leng
dict.say = say
dict.join = joi
## done with the global methods, remove them
del(rpr, stri, inte, say, joi, ma, filt, redu)
## show examples if called standalone
if (__name__ == '__main__'):
i = int(5)
n = i + 5
n.say()
i = i.times(5).divided_by(3).plus(2)
i.str().int().str().repr().say()
s = 'Tree'
i = str(s)
i = i.plus(' and dog\n').times(2)
i.repr().say()
def test(item):
return '%s!' % item
l = ['test', 'this', 'out', 'now']
i = list(l)
i = i.times(2)
i.join(' ').say()
i.map(test).say()
t = ('test', 'this', 'out', 'now')
i = tuple(t)
i = i.plus(('hi', 'there'))
i.join('+').repr().say()
i.map(test).say()
d = {'test': 'this', 'out': 'now'}
i = dict(d)
i.len().say()
It's not the most "pythojnic" way to do things, but it works for me.
Ps. I still have a hard time belieiving that after all the time you've
spent on comp.lang.lisp, comp.lang.ruby and comp.lang.python you still
don't understand these basic concepts...if that's really true, I would
never use your consulting service!
Regards,
Jorda
The learning-process is an important part of the evaluation.
>> how do I define something into the top-level namespace? I assume I
>> could place it into the root-package of my project, into the __init__
>> function.
>>
>> But how do I place it within my computers python installation (the big
>> init)?
>
> When you just say:
>
> def blah(): pass
>
> Now 'blah' function is in the top-level namespace, just like global
> variables. Or if it's in a different file, you'd say 'from blah import
> *'. You honestly don't know this?!??
I know how to define it:
--- myBlahWithImport.py ---
from mylib import blah
if (__name__ == '__main__'):
blah()
--- end file ---
what I dont know is, how to negate the need of the import statement.
--- myBlah.py ---
if (__name__ == '__main__'):
blah()
--- end file ---
>> I am aware of this technique.
>>
>> But I want to modify existent classes, without touching their code.
>
> The only way to do this is to explicitly subclass the existent classes
> with your own class and modify what you want there in your subclass
> (see below), or use multiple inheritence as I suggested previously.
>
>> I've noticed some interesting code on you website:
>>
>> "
>> class file(file):
>> def reopen(self, name=None, mode='w', bufsize=None):
>> ...
>>
>> fh = file('test.txt', 'rb')
>> print fh # <open file 'test.txt', mode 'rb' at 0xb7c92814>
>> fh.reopen(mode='wb')
>> "
>> http://rightfootin.blogspot.com/2006/09/ruby-reopen.html
>>
>> does this mean that I can add a method to a class in a similar way with
>> ruby? (by using class class-name(class-name): )
>
> Basically, yes. In ruby you can reopen base classes; in python you can
> get the same effect by subclassing the base classes with the same name
> as the base class, then instantiating all your objects as that class.
> This is the exact same idea as a "super-duper super class" as I
> mentioned above.
That's a part of the construct I was looking for.
>> but the limitation is that I cannot do this with the python build-in
>> types?:
>>
>> http://rightfootin.blogspot.com/2006/08/of-rocks-and-reptiles.html
>
> You can subclass buit-in types using the same name as the parent class.
So, that's a 2nd part of the constrcut I was looking for.
btw: from which class does "int" inherit?
> In fact here is what I use:
>
> ## my little library to make python more OO
> ## i.e., to get rid of the top-level junk...
> ## or at least to hide it behind some pretty
> ## object attributes :)
> ##
> ## YMMV - and don't complain if you don't
> ## like it; I wrote it for ME, not you
> ##
> ## Jordan Callicoat < Monke...@gmail.com >
>
> ## some global methods so we can use them
> ## to set up the class methods
... (many code I'll review at a later point)
> It's not the most "pythojnic" way to do things, but it works for me.
>
> Ps. I still have a hard time belieiving that after all the time you've
> spent on comp.lang.lisp, comp.lang.ruby and comp.lang.python you still
> don't understand these basic concepts...if that's really true, I would
> never use your consulting service!
"CONSTRUCT - Adding Functionality to the Overall System"
This is not a basic concept.
Although in smaltalk and ruby is very simple.
But I've selected to use Python.
.
One (bad) solution is to write in your sitecustomize.py the following:
$ echo /usr/lib/python/sitecustomize.py
import __builtin__
class Object(object):
def debug(self):
print 'some debug info'
__builtin__.object = Object
then you can do for instance
>>> class C(object): pass
>>> C().debug()
some debug info
All class inheriting from object will have the additional debug method.
However I DO NOT
RECOMMEND THIS SOLUTION FOR ANY SERIOUS WORK. For instance, it broke my
IPython installation and I am pretty sure it will broke other things
too.
But it may work for debugging purposes, if not for production use, so I
thought it was worth
posting.
Michee Simionato
> One (bad) solution is to write in your sitecustomize.py the following:
>
> $ echo /usr/lib/python/sitecustomize.py
> import __builtin__
>
> class Object(object):
> def debug(self):
> print 'some debug info'
>
> __builtin__.object = Object
>
> then you can do for instance
>
>
>>>>class C(object): pass
>>>>C().debug()
>
> some debug info
>
> All class inheriting from object will have the additional debug method.
But sadly not the built-in types like int and str, which is what our
trollish friend wants to do (for some reason best known to himself).
> However I DO NOT
> RECOMMEND THIS SOLUTION FOR ANY SERIOUS WORK. For instance, it broke my
> IPython installation and I am pretty sure it will broke other things
> too.
> But it may work for debugging purposes, if not for production use, so I
> thought it was worth
> posting.
regards
Steve
I insist on methods, and It seems that I stay with Python.
The effort for me to rework python to become more OO is much lesser,
than the effort I would have to rework Ruby to become more (this and
that).
http://case.lazaridis.com/wiki/Lang
And I've already started to like 2 things on python:
* the missing "end" statement and
* (I don't believe I write this) enforced indentation.
.
Followup thread:
[Watching this topic] CONSTRUCT - New/Old Style Classes,
build-in/extension types
http://groups.google.com/group/comp.lang.python/browse_frm/thread/493d71f3dd09939b