class declaration shortcut

  • Thread starter =?iso-8859-1?q?Luis_M._Gonz=E1lez?=
  • Start date
S

Steven Bethard

Luis said:
This is the closest we got so far to the intended result.
If there was a way to enter attributes without quotes, it would be
almost identical.

Ok, below is the Python code so that the following works::

class Person(Struct): "name birthday children"

Note that
* The "Person" name is not repeated
* The attribute names are not individually quoted
* It's two characters shorter than the Ruby code::

Person = Struct.new:)name, :birthday, :children)

Is that good enough? ;-)

STeVe

class InitFromSlots(type):
def __new__(meta, name, bases, bodydict):
slots = bodydict.get('__doc__', '').split()
bodydict.setdefault('__slots__', slots)
if slots and '__init__' not in bodydict:
parts = ['def __init__(self, %s):' % ', '.join(slots)]
for slot in slots:
parts.append(' self.%s = %s' % (slot, slot))
exec '\n'.join(parts) in bodydict
super_new = super(InitFromSlots, meta).__new__
return super_new(meta, name, bases, bodydict)

class Struct(object):
__metaclass__ = InitFromSlots
__slots__ = ()
def _items(self):
for name in self.__slots__:
yield name, getattr(self, name)
def __repr__(self):
args = ', '.join('%s=%r' % tup for tup in self._items())
return '%s(%s)' % (type(self).__name__, args)
def __iter__(self):
for name in self.__slots__:
yield getattr(self, name)
def __getstate__(self):
return dict(self._items())
def __setstate__(self, statedict):
self.__init__(**statedict)
 
S

Steven D'Aprano

Mh. I suspect there's also more to it than I see now, but this
__name__ seems quite useless to me. What if I rebind the class'
name after definition? Or is it really just for some manual
introspection? If it is, it seems a bit of an overkill to me.

Overkill? Storage of a single attribute holding a (usually short) string
is overkill?

The thing to remember is that the link between names and objects in
Python is one-way only. Names (by definition) have to know which object
they are bound to. But objects don't know what name, or names, (if any)
are bound to themselves. Yes, they *could* keep a list of the names bound
to them, but that would be a lot of work at runtime for little benefit.

So if you rebind a name, the objects can't tell. And generally you
wouldn't want them to. Something like the following is rightfully quite
rare:
'something else'

Normally the reason for rebinding classes, functions etc. are (1) to save
typing and (2) an optimization to save name look-ups.

# slow way
for item in sequence:
package.module.function(item)

# faster way
f = package.module.function
for item in sequence:
f(item)

When you do that, you wouldn't expect the __name__ of some.module.function
to change to f, and it doesn't.

The downside is that on the rare corner case where you do want the
__name__ of an object to change, it doesn't.
 
B

Bjoern Schliessmann

Steven said:
Overkill? Storage of a single attribute holding a (usually short)
string is overkill?

No, but storing the first name a class is bound to in it is a bit
of, IMHO.
When you do that, you wouldn't expect the __name__ of
some.module.function to change to f, and it doesn't.

But what is it for then? =) Showing the first name the class was
bound to?

Regards,


Björn
 
A

Arnaud Delobelle

No, but storing the first name a class is bound to in it is a bit
of, IMHO.

Don't see it as the first name a class is bound to, but rather as the
name a class is defined as.
If class_object.__name__ == 'Foo' it means that somewhere in your code
there is a class definition:

class Foo:
# stuff

Same for function: if function_object.__name__ == 'bar' it means that
somewhere you have

def bar(...):
# stuff

(Of course this is not the case if you use another way to define
functions or classes, e.g. type() )
But what is it for then? =) Showing the first name the class was
bound to?

What I described above is quite useful I think. The alternative
(anonymous classes) is that given an object myobj you have no means to
find out what its class is (by that I mean to be able to locate the
class definition in your source code), apart from stabbing in the dark
(i.e. trying type(myobj)==someclass until successful).
 
B

Bjoern Schliessmann

Arnaud said:
Don't see it as the first name a class is bound to, but rather as
the name a class is defined as.
If class_object.__name__ == 'Foo' it means that somewhere in your
code there is a class definition:

class Foo:
# stuff

Same for function: if function_object.__name__ == 'bar' it means
that somewhere you have

def bar(...):
# stuff

(Of course this is not the case if you use another way to define
functions or classes, e.g. type() )

This is somehow contrary to my understanding of the Python names
concept.

What if I use a loop to define several classes based on data --
they'll all have the same __name__ unless I change it manually.

Having this __name__ attribute set seems to me like "magic behind
the lines" which Python strives to evade, doesn't it? Personally,
I'd prefer inserting a mechanism for this manually if and when I
really need the functionality, but see below.
What I described above is quite useful I think. The alternative
(anonymous classes) is that given an object myobj you have no
means to find out what its class is (by that I mean to be able to
locate the class definition in your source code), apart from
stabbing in the dark (i.e. trying type(myobj)==someclass until
successful).

In the typical case where you have one name per class definition,
yes.

Perhaps I'm lacking a typical application of __name__; that must be
why I'm so stubborn here ;)

Regards,


Björn
 
A

Arnaud Delobelle

This is somehow contrary to my understanding of the Python names
concept.

What if I use a loop to define several classes based on data --
they'll all have the same __name__ unless I change it manually.

Well that's not a typical way of defining classes. It is then your
job to name those classes.
Having this __name__ attribute set seems to me like "magic behind
the lines" which Python strives to evade, doesn't it? Personally,
I'd prefer inserting a mechanism for this manually if and when I
really need the functionality, but see below.

So you want a Class object without a __name__, and then you would
subclass it to NamedClass with a __name__.
OTOH every class that you define in python using the 'class' keyword
has an obvious name (the identifier that follows the 'class' keyword),
so it seems natural to me to endow each defined class with a __name__.
In the typical case where you have one name per class definition,
yes.

As you say this is the typical case, and a __name__ attribute is very
useful in this case. For the minority of cases when you have a class
factory for example, then I guess it is your responsibility to name
the class appropriately.

IMHO if you create classes in a way that makes it impossible to name
them naturally, then it is likely that you are misusing the class
object.
Perhaps I'm lacking a typical application of __name__; that must be
why I'm so stubborn here ;)

Here are 3 (please correct me if I'm wrong)
'(i__main__\nFoo\np0\n(dp1\nb.'
 
M

MonkeeSage

I've come across a code snippet in www.rubyclr.com where they show how
easy it is to declare a class compared to equivalent code in c#.
I wonder if there is any way to emulate this in Python.

I posted like 10 minutes ago, but it looks like it didn't go through.
The ruby code is not an easy way to declare a class, it is a ruby
class for creating c-like struct objects.

This is the basic idea behind the ruby Struct class (but this is quick
and dirty, the real implementation is different and done in c, but you
should get the basic idea):

class Struct2
def initialize(*args)
@@attrs = []
args.each { |arg|
eval("class << self; attr_accessor :#{arg} end")
@@attrs.push(arg)
}
end
def new(*args)
args.each_index { |i|
eval("self.#{@@attrs}=args")
return self
}
end
end

Person = Struct2.new:)name)
bob = Person.new('bob')
puts bob.name


A python equiv. would be something like:

class Struct():
def __init__(self, *args):
self.attrs = []
for arg in args:
setattr(self, arg, None)
self.attrs.append(arg)
def __call__(self, *args):
for i in range(len(args)):
setattr(self, self.attrs, args)
return self

Person = Struct('name')
bob = Person('bob')
print bob.name

Regards,
Jordan
 
?

=?iso-8859-1?q?Luis_M._Gonz=E1lez?=

I've come across a code snippet inwww.rubyclr.comwhere they show how
easy it is to declare a class compared to equivalent code in c#.
I wonder if there is any way to emulate this in Python.

I posted like 10 minutes ago, but it looks like it didn't go through.
The ruby code is not an easy way to declare a class, it is a ruby
class for creating c-like struct objects.

This is the basic idea behind the ruby Struct class (but this is quick
and dirty, the real implementation is different and done in c, but you
should get the basic idea):

class Struct2
def initialize(*args)
@@attrs = []
args.each { |arg|
eval("class << self; attr_accessor :#{arg} end")
@@attrs.push(arg)
}
end
def new(*args)
args.each_index { |i|
eval("self.#{@@attrs}=args")
return self
}
end
end

Person = Struct2.new:)name)
bob = Person.new('bob')
puts bob.name

A python equiv. would be something like:

class Struct():
def __init__(self, *args):
self.attrs = []
for arg in args:
setattr(self, arg, None)
self.attrs.append(arg)
def __call__(self, *args):
for i in range(len(args)):
setattr(self, self.attrs, args)
return self

Person = Struct('name')
bob = Person('bob')
print bob.name

Regards,
Jordan



Thanks for your detailed reply!
So after all, the www.rubyclr.com code is not a fair comparison.
Because the c# code shows a class definition, and the ruby code shows
a struct definition, which is not equivalent to a class.
Is that right?
 
M

MonkeeSage

Thanks for your detailed reply!
So after all, the www.rubyclr.com code is not a fair comparison.
Because the c# code shows a class definition, and the ruby code shows
a struct definition, which is not equivalent to a class.
Is that right?

Well c sharp has a struct type, but it's basically just a class, so in
that sense the comparison is accurate. But I don't think the ruby code
is supposed to be a one to one comparison (you could write a similar
Struct class in c sharp too). I assume that what the author there was
trying to say was that ruby is a higher-level language / has more
syntactic sugar than c sharp many times. The same can be said of
python as well, though python is a bit more reserved about adding
sugar (ruby is more aligned with perl in TMTOWTDI, python is more like
"There should be one -- and preferably only one -- obvious way to do
it").

Regards,
Jordan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,778
Messages
2,569,605
Members
45,238
Latest member
Top CryptoPodcasts

Latest Threads

Top