Google Groups unterstützt keine neuen Usenet-Beiträge oder ‑Abos mehr. Bisherige Inhalte sind weiterhin sichtbar.

classes

0 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Pablo

ungelesen,
19.07.2003, 16:37:1019.07.03
an
Hello everyone

I'm rather new to Python and have a problem I hope someone can help me
solve.
I'm used to Java syntax and would like to make a class which holds a
connection object to PostgreSQL database.
I want to make this class as a singleton, and
allow creation only of one instance of the class.

code in Java would like more or less like this:

class Connection{
private static Connection instance = null;
private DBConnection = null; // in python's case it would be pgobject returned
be connect()

private Connection(){
DBConnection = pg.DB();
}

public static Connection getInstance(){
if(instance == null)
instance = new Connection();
return instance;
};

How can I do the same thing in Python?
How can I declare a static field (and private) of a class and allow access to it only by
a static method?
Can I forbid to instantiate more than one object?

I'd be grateful if someone can explain it to me or send me to the good
resource with description about classes which would have some comparisons
of syntax regardig Java or C++.

Best regards
Pablo

Pablo

ungelesen,
19.07.2003, 16:46:3419.07.03
an
Hello everyone

I have a problem with classes and hope someone can help me.
I'm used to Java and want to make a singleton class which would allow to
create only one instance of the class.
In Java it looks as follows:
public class DBConnection{
private static DBConnection instance = null;
private Conn conn = null; // it is supposed to be object returned be
pg.connect() method of the PyGreSQL module

/* a constructor must be private to forbid instantiation of the class */
private DBConnection(){
conn = new Conn();
}

public static DBConnection getInstance(){
if(instance == null)
instance = new DBConnection();
return instance;
}
};

How can I do the same in Python?
My main problems are:
1) how to declare a static field (class field not object field)
2) how to declare a static method
3) how to declare a private constructor (is it possible?)

Can someone help me or point me to some documentation with strong emphasis
on classes? It would be perfect if that documentation had some comparisons
with classes in Java or C++.

Best regards
Pablo

Pablo

ungelesen,
19.07.2003, 16:48:1619.07.03
an
I am sorry my post was sent twice.

Dan Bishop

ungelesen,
19.07.2003, 22:26:0819.07.03
an
"Pablo" <pa...@bogus.domain.org> wrote in message news:<pan.2003.07.19....@bogus.domain.org>...

> Hello everyone
>
> I have a problem with classes and hope someone can help me.
> I'm used to Java and want to make a singleton class which would allow to
> create only one instance of the class.
...[snip]...

> How can I do the same in Python?
> My main problems are:
> 1) how to declare a static field (class field not object field)

<nitpick>You can't. There are no variable declarations in
Python.</nitpick> You can use static fields, though.

>>> class HasStaticField:
... field = 4
...
>>> HasStaticField.field
4

> 2) how to declare a static method

class HasStaticMethod:
def method(arg0, arg1): # note the lack of "self"
# do something with arg0 and arg1
method = staticmethod(method)

> 3) how to declare a private constructor (is it possible?)

It's not possible (afaik) to define a private constructor. But it is
possible to enforce that a constructor can be called only once.

class SingletonError(Exception):
pass

class Singleton:
__instance = None
def __init__(self):
if Singleton.__instance is None:
# initialization code
Singleton.__instance = self
else:
raise SingletonError()
def getInstance():
if Singleton.__instance is None:
Singleton()
return Singleton.__instance
getInstance = staticmethod(getInstance)

Pablo

ungelesen,
20.07.2003, 08:30:1120.07.03
an
[cut]

>> 2) how to declare a static method
>
> class HasStaticMethod:
> def method(arg0, arg1): # note the lack of "self"
> # do something with arg0 and arg1
> method = staticmethod(method)

That's not exactly what I wanted.
I would prefer something like this:
class StaticMethod:


__instance = None
def __init__(self):

if StaticMethod.__instance is None:
StaticMethod.__instance = self
else:
raise Exception("Constructor may be invoked only once")
def getInstance():
if StaticMethod.__instance is None:
StaticMethod.__instance = StaticMethod()
return StaticMethod.__instance

m = StaticMethod.getInstance()
but Python does not allow to invoke any class method without providing an
instance of the class object

I've been thinking about Python classes and modules and found out that it
is possible in Python to create an object in some module and use a
reference to it from other modules. In Java it's not possible to create
any object outside of any class.
So my problem would be solved if I could create a class which would be
seen only in its module (something like private class). Then I could
create an object and simply use it across my application.
It would behave like a static object since it
wouldn't be possible to create another object in other modules (since the
class would be visible only it its module), and it also wouldn't be
possible to create another object in its module (there is no reason for
it).

Is it possible to create a class and forbid its use outside its module?


Thanks for a usefull reply.
Pablo

Pedro Werneck

ungelesen,
20.07.2003, 10:23:3720.07.03
an
"Pablo" <pa...@bogus.domain.org> wrote in message

> Can someone help me or point me to some documentation with strong emphasis


> on classes? It would be perfect if that documentation had some comparisons
> with classes in Java or C++.

Guido's essay on new style classes is a good starting point...

http://www.python.org/2.2.1/descrintro.html

Steven Taschuk

ungelesen,
20.07.2003, 14:04:2020.07.03
an
Quoth Pablo:

> [cut]
> >> 2) how to declare a static method
> >
> > class HasStaticMethod:
> > def method(arg0, arg1): # note the lack of "self"
> > # do something with arg0 and arg1
> > method = staticmethod(method)
>
> That's not exactly what I wanted.
[...]

> but Python does not allow to invoke any class method without providing an
> instance of the class object

Sure it does. Allowing that is the purpose of the "staticmethod"
call in Dan's example.

Try it yourself:

>>> class HasStaticMethod(object):
... def mystaticmethod(x, y):
... print x, y
... mystaticmethod = staticmethod(mystaticmethod)
...
>>> HasStaticMethod.mystaticmethod(3, 4)
3 4

No instance of HasStaticMethod exists here.

[...]


> So my problem would be solved if I could create a class which would be
> seen only in its module (something like private class). Then I could
> create an object and simply use it across my application.

[...]


> Is it possible to create a class and forbid its use outside its module?

No, not really. (There's a philosophical reason: Java encourages
the attitude that other programmers can't be trusted to use your
code correctly, while Python encourages the attitude that other
programmers know what they're doing. Thus there's not a lot of
mechanisms in Python to forbid other programmers from doing things
with your code.)

For the particular problem you're interested in -- singletons --
here are a few approaches:

First, use __new__ trickery:

_the_instance = None
class MySingleton(object):
def __new__(self):
global _the_instance
if _the_instance is None:
_the_instance = object.__new__(self)
return _the_instance

Example use:

>>> x = MySingleton()
>>> y = MySingleton()
>>> x is y # same object!
True

In this approach, users create instances of MySingleton as they
would for any other class (rather than by calling a getInstance
classmethod) -- that action just happens to return the same object
always.

One gotcha with this approach can be observed by adding

def __init__(self):
print 'running __init__ on instance %s' % id(self)

Then we see

>>> x = MySingleton()
running __init__ on instance 1075795852
>>> y = MySingleton()
running __init__ on instance 1075795852
>>> x is y
True

As shown, each "instantiation" runs __init__ on the single
instance again. If you have initialization which should occur
only when the single instance is actually created:

_the_instance = None
class MySingleton(object):
def __new__(self):
global _the_instance
if _the_instance is None:
_the_instance = object.__new__(self)
_the_instance._my_init()
return _the_instance
def _my_init(self):
pass # one-time initialization here

(Another possible issue with this approach arises when subclassing
MySingleton. Details left as an exercise.)

Second approach: Use a metaclass. See
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/102187>

Third: forget about singletons and use a Borg. See
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531>
(With Borgs, multiple instances may exist, but they share state.)

Fourth: rethink the idea that a database connection should be a
singleton. See
<http://c2.com/cgi/wiki?SingletonsAreEvil>
and linked pages for discussion on the merits of singletons.

--
Steven Taschuk 7\ 7'Z {&~ .
stas...@telusplanet.net Y r --/hG-
(__/ )_ 1^1`

Pablo

ungelesen,
20.07.2003, 17:29:1220.07.03
an
> Sure it does. Allowing that is the purpose of the "staticmethod"
> call in Dan's example.

Yes You're right and Dan as well.
I just didn't know that that 'staticmethod' existed and tried to do "Java
style" static method which obviously didn't work

The trick with __new__ is usefull. I must read some more about classes in
Python. Thanks to Pedro for a link.

Cheers
Pablo

Michele Simionato

ungelesen,
21.07.2003, 08:51:1621.07.03
an
Steven Taschuk <stas...@telusplanet.net> wrote in message news:<mailman.1058723911...@python.org>...

> For the particular problem you're interested in -- singletons --
> here are a few approaches:
>
> First, use __new__ trickery:
>
> _the_instance = None
> class MySingleton(object):
> def __new__(self):
> global _the_instance
> if _the_instance is None:
> _the_instance = object.__new__(self)
> return _the_instance

Why are you using a global here and not something like


class MySingleton(object):
_the_instance = None
def __new__(cls):
if cls._the_instance is None:
cls._the_instance = object.__new__(self)
return cls._the_instance

?


Unfortunately, I see that this recipe is not very recommendable. I have
just submitted a fix which seems to work:

class Singleton(type):
def __init__(cls,name,bases,dic):
super(Singleton,cls).__init__(name,bases,dic)
cls.instance=None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance=super(Singleton,cls).__call__(*args,**kw)
return cls.instance

Here is how it works under inheritance and avoids the problem with
calling __init__ twice:

class C:
__metaclass__=Singleton
def __init__(self):
print "C: initializing ",self

class D(C):
def __init__(self):
print "D: initializing ",self

c1=C() # => C: initializing <__main__.C object at 0x4031c0ac>
c2=C() # no output
d=D() # D: initializing <__main__.D object at 0x4031c02c>
print c1 is c2 # => yes


> Third: forget about singletons and use a Borg. See
> <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531>
> (With Borgs, multiple instances may exist, but they share state.)
>
> Fourth: rethink the idea that a database connection should be a
> singleton. See
> <http://c2.com/cgi/wiki?SingletonsAreEvil>
> and linked pages for discussion on the merits of singletons.


HTH,
Michele

Steven Taschuk

ungelesen,
21.07.2003, 20:37:0121.07.03
an
Quoth Michele Simionato:

> Steven Taschuk <stas...@telusplanet.net> wrote in message news:<mailman.1058723911...@python.org>...
[...]

> > _the_instance = None
> > class MySingleton(object):
> > def __new__(self):
> > global _the_instance
> > if _the_instance is None:
> > _the_instance = object.__new__(self)
> > return _the_instance
>
> Why are you using a global here and not [a class attribute]

The memory of that thread a little while back about using __del__
with singletons. If the instance is referenced by a class
attribute, the cyclic reference prevents the __del__ from being
used. If the cycle goes through a module attribute, though, the
zapping of module dicts during shutdown breaks the cycle and lets
the __del__ run. (Whether all this is true depends on the version
of Python, I think, but I don't know the details.)

This might be relevant to the OP, whose example was a singleton
representing the single database connection used by an entire
application -- in such a case, __del__ would be a natural place to
make sure the connection is closed properly.

I should have explained this bit of trickery. :(

[...]


> > Second approach: Use a metaclass. See
> > <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/102187>
>
>
> Unfortunately, I see that this recipe is not very recommendable. I have
> just submitted a fix which seems to work:

[...]

Nice!

--
Steven Taschuk Aral: "Confusion to the enemy, boy."
stas...@telusplanet.net Mark: "Turn-about is fair play, sir."
-- _Mirror Dance_, Lois McMaster Bujold

Michele Simionato

ungelesen,
23.07.2003, 17:11:4723.07.03
an
Steven Taschuk <stas...@telusplanet.net> wrote in message news:<mailman.1058833821...@python.org>...

> Quoth Michele Simionato:
> > Steven Taschuk <stas...@telusplanet.net> wrote in message news:<mailman.1058723911...@python.org>...
> [...]
> > > _the_instance = None
> > > class MySingleton(object):
> > > def __new__(self):
> > > global _the_instance
> > > if _the_instance is None:
> > > _the_instance = object.__new__(self)
> > > return _the_instance
> >
> > Why are you using a global here and not [a class attribute]
>
> The memory of that thread a little while back about using __del__
> with singletons. If the instance is referenced by a class
> attribute, the cyclic reference prevents the __del__ from being
> used. If the cycle goes through a module attribute, though, the
> zapping of module dicts during shutdown breaks the cycle and lets
> the __del__ run. (Whether all this is true depends on the version
> of Python, I think, but I don't know the details.)
>
> This might be relevant to the OP, whose example was a singleton
> representing the single database connection used by an entire
> application -- in such a case, __del__ would be a natural place to
> make sure the connection is closed properly.
>
> I should have explained this bit of trickery. :(
>
Thanks for the explation, I missed that thread.

Michele

0 neue Nachrichten