"literal" objects

M

Moosebumps

I've googled all over for this but can't find an answer...

I'm fairly new to Python, and wondering if you can just list a bunch of
objects as data. For example, in C you would just do something like this:

struct
{
int a;
float b;
} mystruct;

mystruct x = { 3, 5.0f };
mystruct y = { 5, 15.0f };

These are just "data". Obviously in python you could just write an init
function like this:

x.a = 3;
x.b = 5;

y.a = 5;
y.b = 15;

And that would work fine, but the programmer in me says that that's a pretty
inelegant way to do it. Why execute code when all you need is to put data
in the program?

A thought that occured to me is that classes are implemented as dictionaries
(correct?). So you could have a dictionary like this:

x = {'a': 3, 'b': 5}
y = {'a': 5, 'b': 15}

This would be the __dict__ attribute of an object I suppose. But I don't
see anyway to assign it to a variable so you could access them like x.a and
y.a. I don't know if this would be a "nice" way to do it or not.

Question 2:

If "subfolder" is a folder under "basefolder", and basefolder contains
"base.py", and subfolder contains "sub.py", how do I import sub.py into
base.py? From what I can tell so far it only works if the files are in the
same directory. I need to be able to do this without modifying any
environment variables or anything. Because the scripts will be run on many
different machines and I have no way of automatically configuring them.

thanks,
MB
 
F

Francis Avila

Moosebumps wrote in message
I've googled all over for this but can't find an answer...

I'm fairly new to Python, and wondering if you can just list a bunch of
objects as data. For example, in C you would just do something like this:

struct
{
int a;
float b;
} mystruct;

mystruct x = { 3, 5.0f };
mystruct y = { 5, 15.0f };

These are just "data". Obviously in python you could just write an init
function like this:

x.a = 3;
x.b = 5;

y.a = 5;
y.b = 15;

Obviously? I have no idea what the above snippet is supposed to correspond
to in Python.

A class is like (using like in a very, very loose sense here) a struct, not
like an instance of a struct. I'm really streching the C analogy in every
possible way, but that much is at least sorta true. The equivalent Python
to your C code is:

class mystruct(object):
def __init__(self, a, b):
self.a = a
self.b = b

x = mystruct(3, 5.0)
y = mystruct(5, 15.0)

Is this what you consider inelegant? If it's too over-engineered (!) for
you, use a more basic data type, like a dict (as you suggest later). Or you
can simply bypass init and assign directly:

x = object()
x.a = 3
x.b = 5.0

But since you *know* the struct's structure, you might as well use __init__
to formalize it. And you're still executing object's __init__, anyway.
And that would work fine, but the programmer in me says that that's a pretty
inelegant way to do it. Why execute code when all you need is to put data
in the program?

The programmer in you is optimizing prematurely and/or trying to turn Python
into C. :)

The point of classes are to package data and a set of operations proper to
that data. C doesn't have classes (although similar concepts can be
emulated with structs and function pointers). Python uses them liberally.
However, one would rarely have such a bare class that's simply holding two
attributes; it would also implement methods that operated on the data it
held. If all you want to do are hold two numbers efficiently, use a
list/tuple or somesuch, and access them by index instead of name (if the
name doesn't matter). Or see below.
A thought that occured to me is that classes are implemented as dictionaries
(correct?). So you could have a dictionary like this:

No. Classes are objects. Dictionaries implement attribute access to
objects (i.e. namespaces).
x = {'a': 3, 'b': 5}
y = {'a': 5, 'b': 15}

This would be the __dict__ attribute of an object I suppose. But I don't
see anyway to assign it to a variable so you could access them like x.a and
y.a. I don't know if this would be a "nice" way to do it or not.

What you're asking for is a "bunch". It's a common cookbook recipe:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52308

class Bunch(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

Use it like x = object() above, except you can preinitialize name/value
pairs:

x = Bunch(a=3, b=5.0)
print x.a # 3
x.z = 'new attribute'

Be careful not to clobber attribute names (object only has __*__ special
names, so you don't need to worry too much).


The moral of this story is that your question is too abstract. What your
data structure should look like depends on what purpose it has, how it is
used, and what requirements it must fulfill. Python can produce *much*
richer data structures than C, what with OO and all, so there are many more
possibilities than simply a C struct.

Further, C is radically different from Python, so it's not healthy to try
and make Python conform to your C expectations. For one, C is a compiled
language, whereas Python is bytecode interpreted. In C, struct only exists
to the compiler and to you--it is an entirely logical construct used to make
coding easier; it, variable names, etc, *cease to exist* when they are
turned into code. This makes C very tight and efficient. But in Python,
even down to the bytecode, name lookups are done, classes and functions are
*real things*, etc. This makes Python very powerful and far easier to use,
but you give up speed. However, you rarely *need* the speed, and there are
always ways of getting alot of it back.
Question 2:

If "subfolder" is a folder under "basefolder", and basefolder contains
"base.py", and subfolder contains "sub.py", how do I import sub.py into
base.py? From what I can tell so far it only works if the files are in the
same directory. I need to be able to do this without modifying any
environment variables or anything. Because the scripts will be run on many
different machines and I have no way of automatically configuring them.

Any directory which contains a file called __init__.py is a package. If you
create such a file in subfolder, you can import sub from base.py as
subfolder.sub.

import subfolder.sub as sub
from subfolder import sub

will both put sub into the current namespace. See the bottom of the page on
the import statement in the Python Language Reference.
 
A

Ahmed MOHAMED ALI

Hi ,

Question 1:

You can use classes like C struct ,here's the way to do

class struct_type
pass:

mystruct = struct_type()
mystruct .a=3
mystruct .b=5.0

Question 2:
sys.append
 
J

John Roth

Moosebumps said:
I've googled all over for this but can't find an answer...

I'm fairly new to Python, and wondering if you can just list a bunch of
objects as data. For example, in C you would just do something like this:

struct
{
int a;
float b;
} mystruct;

[rest snipped]

As Francis Avila said in another response, why would you really
want to do this? However, if you do, there are a couple of
easy ways.

[untested code]
class someData:
pass

a = someData()
a.__dict__.update({item1: "Hi", item2: "there"})

print "%s %s" % (a.item1, a.item2) --> "Hi there"

However, frankly it's easier (and much clearer) to
use a dictionary:

a = {}
a.update({item1: "Hi", item2: "there"})
print "%(item1)s %(item2)s" % a --> "Hi there"

HTH

John Roth
 
D

Donn Cave

"Moosebumps said:
I'm fairly new to Python, and wondering if you can just list a bunch of
objects as data. For example, in C you would just do something like this:

struct
{
int a;
float b;
} mystruct;

mystruct x = { 3, 5.0f };
mystruct y = { 5, 15.0f };

These are just "data". Obviously in python you could just write an init
function like this:

x.a = 3;
x.b = 5;

y.a = 5;
y.b = 15;

Well, strictly speaking I think the obvious init function would
be looking more like self.a = 3, etc. What you have written is
legal, if not obvious. (And lose the semicolons!)
And that would work fine, but the programmer in me says that that's a pretty
inelegant way to do it. Why execute code when all you need is to put data
in the program?

I think the above paragraph may account for the dismissive
responses you have gotten so far. While your analysis of the
Python model is structurally fairly sound as far as it goes,
your instincts about what is elegant are utterly misguided!
You are not the first person to ever experience this, though.
A thought that occured to me is that classes are implemented as dictionaries
(correct?). So you could have a dictionary like this:

x = {'a': 3, 'b': 5}
y = {'a': 5, 'b': 15}

This would be the __dict__ attribute of an object I suppose. But I don't
see anyway to assign it to a variable so you could access them like x.a and
y.a. I don't know if this would be a "nice" way to do it or not.

class A:
def __init__(self):
self.__dict__.update({'a': 3, 'b': 5})
x = A()
print x.a, x.b

Would it be nice? No, it would be horrible, unless you had some
very compelling reason to do this, in which case it would be fine.
Question 2:

If "subfolder" is a folder under "basefolder", and basefolder contains
"base.py", and subfolder contains "sub.py", how do I import sub.py into
base.py? From what I can tell so far it only works if the files are in the
same directory. I need to be able to do this without modifying any
environment variables or anything. Because the scripts will be run on many
different machines and I have no way of automatically configuring them.

import sys
sys.path.insert(0, 'basefolder/subfolder')

Donn Cave, (e-mail address removed)
 
B

Bengt Richter

class A:
def __init__(self):
self.__dict__.update({'a': 3, 'b': 5})
x = A()
print x.a, x.b

Would it be nice? No, it would be horrible, unless you had some
very compelling reason to do this, in which case it would be fine.
This form of the above can be useful, though:

class A:
def __init__(self, **kw):
self.__dict__.update(kw)
x = A(a=3, b=5)
print x.a, x.b

Since you can then also continue with

y = A(a='Happy', b='Holidays')
print y.a, y.b

;-)

Regards,
Bengt Richter
 
B

Bjorn Pettersen

It wouldn't -- using a proper __init__ initializer when you know the
structure of the object is by far the better approach. If you didn't
care about accessing the contained items using dot notation, you could
simply do:

x = dict(a=3, b=5)
y = dict(a=5, b=15)

If you need dot notation, there are several ways of doing it. Continuing
with a dict subclass you can e.g. do:
... def __setattr__(self, attr, val):
... self[attr] = val
... def __getattr__(self, attr):
... return self[attr]
...
This form of the above can be useful, though:

class A:
def __init__(self, **kw):
self.__dict__.update(kw)
x = A(a=3, b=5)
print x.a, x.b
[...]

This is the "inverse" of my example above. Which one I'd choose depends
on how much I know about the objects and if there are many other mehtods
I need to add. E.g. the __setattr__ in Dict above makes it more typing
intensive to add methods to the class.

If your use case for this simple struct is to have a very large number
of such objects, this might be a legitimate use of __slots__, i.e. the
following class will take less memory than a dictionary solution (but
not enough less that it makes any sense unless you have _many_ instances
of it):
... __slots__ = 'a b'.split()
... def __init__(self, a, b):
... self.a, self.b = a, b
... def __repr__(self):
... return '<Data a=%s b=%s>' % (self.a, self.b)
... __str__ = __repr__
...
it also has the side-effect that you can't assign to new attributes:
Traceback (most recent call last):

which is the price we pay for this memory optimization :)

Regards,
Bengt Richter


-- bjorn
 
O

Oren Tirosh

.
A thought that occured to me is that classes are implemented as dictionaries
(correct?). So you could have a dictionary like this:

x = {'a': 3, 'b': 5}
y = {'a': 5, 'b': 15}

This would be the __dict__ attribute of an object I suppose. But I don't
see anyway to assign it to a variable so you could access them like x.a and
y.a. I don't know if this would be a "nice" way to do it or not.

You can update an object's __dict__ from an existing dictionary:

obj.__dict__.update(x) would make obj.a==3 and obj.b==5

You can do this in an object's constructor and combine it with keyword
arguments to get a nifty struct-like class:

class Struct:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

If you want something a bit more fancy, you can add the following __repr__
method to the Struct class, so you can now print these structs, too:

def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
', '.join(['%s=%s' % (k, repr(v)) for k,v in self.__dict__.items()]))
.... pass
....
Oren
 
D

David Bolen

Francis Avila said:
Is this what you consider inelegant? If it's too over-engineered (!) for
you, use a more basic data type, like a dict (as you suggest later). Or you
can simply bypass init and assign directly:

x = object()
x.a = 3
x.b = 5.0

But since you *know* the struct's structure, you might as well use __init__
to formalize it. And you're still executing object's __init__, anyway.

Another way to accomplish the above but in a declarative way, needn't
even involve the use of __init__ - you could just:

class mystruct:
a = 3
b = 5.0

and you're done. Technically the names 'a' and 'b' are class level,
but they'll work the same way as instance variables unless they are
assigned to (in which case they become local to the instance). This
also lets you access them as class level if this is really just a
single grouping of data rather than something you want multiple
instances of.

Of course, this code is still being "executed" so that doesn't address
the OP's issue on that front (although IMO that's really a non-issue).

-- David
 
P

Pekka Pessi

Moosebumps said:
mystruct x = { 3, 5.0f };
mystruct y = { 5, 15.0f };
These are just "data". Obviously in python you could just write an init
function like this:
x.a = 3;
x.b = 5;
y.a = 5;
y.b = 15;
And that would work fine, but the programmer in me says that that's a pretty
inelegant way to do it. Why execute code when all you need is to put data
in the program?

This depends what you plant to do. Easiest way to initialize the
__dict__ is with code something like this:

class AnyStruct:
def __init__(self, **kw):
self.__dict__.update(kw)

The ** in the __init__ signature means that it puts all named arguments
in the dictionary kw.

You can then use your structure class like this:

x = AnyStruct(a = 3, b = 5)

Of course, this is "nice" trick to utilize whenever you initialize an
instance.

If you have some mandatory argument, you can require that callers sets
them with

class MyStruct:
def __init__(self, a, b, **kw):
self.a = a
self.b = b
self.__dict__.update(kw)

then

x = MyStruct(3, 5)

does same as

x = MyStruct(a = 3, b = 5)

but the latter is a bit more readable.

--Pekka
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top