any ways to judge whether an object is initilized or not in a class

M

momobear

hi, I am puzzled about how to determine whether an object is
initilized in one class, anyone could give me any instructions?
here is an example code:

class coffee:
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

in C++ language we must initilized a variable first, so there is no
such problem, but in python if we don't invoke a.boil(), we will not
get self.temp to be initilized, any way to determine if it's initilzed
before self.temp be used.
 
D

Diez B. Roggisch

momobear said:
hi, I am puzzled about how to determine whether an object is
initilized in one class, anyone could give me any instructions?
here is an example code:

class coffee:
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

in C++ language we must initilized a variable first, so there is no
such problem, but in python if we don't invoke a.boil(), we will not
get self.temp to be initilized, any way to determine if it's initilzed
before self.temp be used.

You want boil to be called __init__, which is python's constructor name.
Then it will be called in a statement like

a = coffee()

automatically.


Diez
 
M

momobear

momobear schrieb:







You want boil to be called __init__, which is python's constructor name.
Then it will be called in a statement like

a = coffee()

automatically.

Diez

sorry, I should add more code to implement my ideas.
class coffee:
def __init__(self):
'''
do something here
'''
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"
 
B

Ben Finney

momobear said:
class coffee:
def __init__(self):
'''
do something here
'''
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

class Coffee(object):
def __init__(self):
self.temp = 20
def boil(self):
self.temp = 80

a = coffee()
if a.temp > 60:
print "it's boiled"

In Python, it's conventional to name classes in TitleCase, and
instances in lower_case.

It's also best to inherit every class from another class, leading to a
single hierarchy for all classes and types. 'object' is the one to
choose if you don't want the behaviour of any other class.


As for the original question: the __init__ method of a class is called
immediately after the constructor, so that's the place to initialise
any instance attributes.
 
D

Duncan Booth

momobear said:
in C++ language we must initilized a variable first, so there is no
such problem, but in python if we don't invoke a.boil(), we will not
get self.temp to be initilized, any way to determine if it's initilzed
before self.temp be used.
The simplest thing is simply never to attempt to use a variable or an
attribute until you know that is has been initialized, so initialize all
variables before using them, and initialize all attributes in the class's
__init__ method.

If you don't have a suitable value for the attribute until later then just
start off with None and then you can check for 'a.boil is not None': if you
forget to check then Python's strong type checking will stop you from using
the None value in an expression expecting a number (or a string).

For cases where you aren't sure whether an object has a specific attribute
you can use getattr with 3 arguments:

if getattr(a, 'boil', 80):
...

If that isn't convenient (or it's a variable rather than an attribute) you
should fall back on the principle that 'is it better to ask forgiveness
than permission': i.e. just try to use the value and handle the exception
which is thrown if it doesn't exist. (If the fallback is to substitute a
simple value use getattr, if the fallback is complicated or takes a long
time to calculate use exception handling).

There is also a function 'hasattr' which will tell you whether or not the
object has the specified attribute, but internally it just calls 'getattr'
and handles the exception so (IMHO) it is generally best just not to bother
with 'hasattr'.
 
J

James Stroud

momobear said:
hi, I am puzzled about how to determine whether an object is
initilized in one class, anyone could give me any instructions?
here is an example code:

class coffee:
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

in C++ language we must initilized a variable first, so there is no
such problem, but in python if we don't invoke a.boil(), we will not
get self.temp to be initilized, any way to determine if it's initilzed
before self.temp be used.

I think you might be looking for hasattr:

class coffee:
def boil(self):
if hasattr(self, 'temp') and self.temp > 60:
print "Its boilt, yo."
else:
self.temp = 80

Other ways to do this are try/except:


class coffee:
def boil(self):
try:
if self.temp > 60:
print "Its bizzle, yo."
return
except AttributeError:
pass
self.temp = 80


Which is not so good in my opinion because it takes too much typing and
makes your fingers hurt at the very tips.

A fun way is with dict.setdefault which might actually be cleanest, but
you loose testing the precondition for the print:

class coffee:
def boil(self):
if self.__dict__.setdefault('temp', 80) > 60:
print "Its bizzle m'wizzle."


py> c = coffee()
py> c.temp
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: coffee instance has no attribute 'temp'
py> c.boil()
Its bizzle m'wizzle.
py> c.temp
80


Of course, the idea is that, in classes, you will be intimately aware of
the attributes of your class via __init__, as others have mentioned, so
you should never really resort to any of the above.

James
 
M

momobear

The simplest thing is simply never to attempt to use a variable or an
attribute until you know that is has been initialized, so initialize all
variables before using them, and initialize all attributes in the class's
__init__ method.

If you don't have a suitable value for the attribute until later then just
start off with None and then you can check for 'a.boil is not None': if you
forget to check then Python's strong type checking will stop you from using
the None value in an expression expecting a number (or a string).

For cases where you aren't sure whether an object has a specific attribute
you can use getattr with 3 arguments:

if getattr(a, 'boil', 80):
...

If that isn't convenient (or it's a variable rather than an attribute) you
should fall back on the principle that 'is it better to ask forgiveness
than permission': i.e. just try to use the value and handle the exception
which is thrown if it doesn't exist. (If the fallback is to substitute a
simple value use getattr, if the fallback is complicated or takes a long
time to calculate use exception handling).

There is also a function 'hasattr' which will tell you whether or not the
object has the specified attribute, but internally it just calls 'getattr'
and handles the exception so (IMHO) it is generally best just not to bother
with 'hasattr'.

thanks for help:), I am puzzled about if I have to use try and except
to determine it. finnal code should like this?
class coffee:
def __init__(self):
'''
do something here
'''
def boil(self):
self.temp = 80

a = coffer()
try:
if a.temp > 60:
print "it's boiled"
except AttributeError:
print "it's not boiled"
 
D

Duncan Booth

momobear said:
thanks for help:), I am puzzled about if I have to use try and except
to determine it. finnal code should like this?
class coffee:
def __init__(self):
'''
do something here
'''
def boil(self):
self.temp = 80

a = coffer()
try:
if a.temp > 60:
print "it's boiled"
except AttributeError:
print "it's not boiled"

No, you should simply do the first of the options I suggested. i.e.
initialise the value

class coffee:
def __init__(self):
self.temp = 20

def boil(self):
self.temp = 80

a = coffee()
if a.temp > 60:
print "it's boiled"
else:
print "it's not boiled"
 
B

Bruno Desthuilliers

Diez B. Roggisch a écrit :
You want boil to be called __init__, which is python's constructor name.

<nitpicking>
Actually, __init__ is the initializer. The proper constructor is __new__.
</nitpicking>
 
B

Bruno Desthuilliers

momobear a écrit :
hi, I am puzzled about how to determine whether an object is
initilized in one class, anyone could give me any instructions?
here is an example code:

class coffee:
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

in C++ language we must initilized a variable first, so there is no
such problem, but in python if we don't invoke a.boil(), we will not
get self.temp to be initilized,

Obviously. This is why it's good form to set all public attributes in
the initializer method:

class Coffee(object):
def __init__(self):
self.temp = 20
def boil(self):
self.temp = 80
 
G

Gabriel Genellina

sorry, I should add more code to implement my ideas.
class coffee:
def __init__(self):
'''
do something here
'''
def boil(self):
self.temp = 80

a = coffer()
if a.temp > 60:
print "it's boiled"

Apart from the other suggestions (ensure full initialization in __init__,
using getattr, using hasattr) you may consider using a class attribute as
a default value:

class Coffee:

temp = 50

def __init__(self):
"do something"

def boil(self):
self.temp = 80

a = Coffee()
print a.temp # 40
a.boil()
print a.temp # 80
 
S

Steve Holden

Bruno said:
Diez B. Roggisch a écrit :

<nitpicking>
Actually, __init__ is the initializer. The proper constructor is __new__.
</nitpicking>
<nitpicking severity="be-kind-to-novices">
Actually you would have to ensure that the class's metaclass was <type
"type"> for that to be true. Classic classes don't *have* a __new__ method.
</nitpicking>

And of course the real answer is that the __init__ method should set a
default value (modulo the sneaky use of class attributes) for any
attributes that might be accessed before other methods get a chance to
set them.

regards
Steve
 
B

Bruno Desthuilliers

Steve Holden a écrit :
<nitpicking severity="be-kind-to-novices">

I'm not sure Diez qualifies as a "novice". And since the OP makes
reference to C++, I assume he's able to grasp the difference between a
constructor and an initializer.
Actually you would have to ensure that the class's metaclass was <type
"type"> for that to be true. Classic classes don't *have* a __new__ method.

Yes, true.

Fact is I stopped using old-style classes some years ago, so I don't
really remember what features they were missing. Thanks for the correction.
 
G

greg

Gabriel said:
you may consider using a class
attribute as a default value:

class Coffee:

temp = 50

Be careful with that, though -- only use it for immutable
values. Doing that with a mutable object, such as a list,
will get you into trouble, since one object is being
shared between all instances.
 
S

Steven D'Aprano

It's also best to inherit every class from another class, leading to a
single hierarchy for all classes and types. 'object' is the one to
choose if you don't want the behaviour of any other class.

What's wrong with old-style classes?

On the plus side:

- Why inherit from something if you don't need to?

- Less typing.

- Attribute-lookup is much faster, perhaps as much as twice as fast.
http://www.python.org/~jeremy/weblog/030506.html

- Documentation on old style classes is more extensive.

- You can't use new style classes for exceptions.



On the minus side:

- Properties don't work as you expect them too.

- Slots don't work at all.


In other words, the only reason why you HAVE to use a new style class is
that you need properties or __slots__. You might WANT to use a new style
class to inherit from built-in types. Otherwise, the choice between old
and new is not very important.
 
B

Ben Finney

Steven D'Aprano said:
What's wrong with old-style classes?

<URL:http://wiki.python.org/moin/NewClassVsClassicClass>

The main ones for me are:

- super() doesn't work.

- property() doesn't work as expected.

- They will disappear in a future version of Python, and the docs
recommend them for backward compatibility with existing code. This
is reason enough to avoid writing classic classes in any new code.

More importantly, it's a reason to educate all new programmers in
using new-style classes and inheritance.
 
S

Steve Holden

Steven said:
What's wrong with old-style classes?

On the plus side:

- Why inherit from something if you don't need to?

- Less typing.

- Attribute-lookup is much faster, perhaps as much as twice as fast.
http://www.python.org/~jeremy/weblog/030506.html

- Documentation on old style classes is more extensive.

- You can't use new style classes for exceptions.
In 2.5 exceptions are new-style objects, thanks to Brett Cannon's PyCon
work from 2006:

Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
Started with C:/Steve/.pythonrc

Python 2.5b2 (trunk:50713, Jul 19 2006, 16:04:09)
[GCC 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
Started with C:/Steve/.pythonrc
On the minus side:

- Properties don't work as you expect them too.

- Slots don't work at all.


In other words, the only reason why you HAVE to use a new style class is
that you need properties or __slots__. You might WANT to use a new style
class to inherit from built-in types. Otherwise, the choice between old
and new is not very important.
Most of the documentation on old-style classes, of course, applies to
new-style classes too.

regards
Steve
 
B

Bruno Desthuilliers

Steven D'Aprano a écrit :
What's wrong with old-style classes?

Almost everything. That's why Python 2.2 introduced new-style classes.
IIRC it was some 6 years ago now.
On the plus side:

- Why inherit from something if you don't need to?

You don't have to inherit. You can also make a class new-style by
setting it's __metaclass__ attribute properly. But that's more typing !-)
- Less typing.

Lol. Six keystrokes in the worst case.
- Attribute-lookup is much faster, perhaps as much as twice as fast.
http://www.python.org/~jeremy/weblog/030506.html

This was in 2003. Did you bother testing now ? with Python 2.4.4:
.... def __init__(self):
.... self.attr = "old"
........ def __init__(self):
.... self.attr = "new"
....
>>> from timeit import Timer
>>> told = Timer('old.attr', 'from __main__ import Old; old=Old()')
>>> tnew = Timer('new.attr', 'from __main__ import New; new=New()')
>>> told.repeat() [0.40867519378662109, 0.39075493812561035, 0.38998913764953613]
>>> tnew.repeat()
[0.58840394020080566, 0.5948030948638916, 0.36941695213317871]

Not really "twice as fast" AFAICT.

Now if you're really favor raw speed over expressivity, then you might
wan to choose another language.
- Documentation on old style classes is more extensive.

Since new-style classes are backward compatible with old-style ones,
almost all the old-style classes documentation applies to new-style ones
as well. Everything else is quite well documented too:
http://www.python.org/doc/newstyle/
- You can't use new style classes for exceptions.

Exceptions are new-style classes in 2.5.
On the minus side:

- Properties don't work as you expect them too.

properties don't work. Period. Properties rely on the descriptor
protocol, which only works with new-style classes.
- Slots don't work at all.
- no support for the descriptor protocol
- no __getattribute__
- no metaclasses
- no proper constructor
- no classmethod
- no super()
In other words, the only reason why you HAVE to use a new style class is
that you need properties or __slots__.

The reason why you have to use new-style classes is that it's the
official Python object model since december 2001 - old-style classes
being kept for compatibility. The reason why you want to use them is
that they provide everything old-style classes did, and *way much more*.
FWIW, if Python didn't have this powerful object model, I would have
switched to another language long ago. And I'm probably not the only one.
You might WANT to use a new style
class to inherit from built-in types.

Since builtin types are all new-style classes, any class inheriting from
a builtin is a new-style class. FWIW, that's one of the reason for the
object model changes way back in 2001.
Otherwise, the choice between old
and new is not very important.

Your opinion. Too bad you're missing some of the most powerful parts of
the language.
 
S

Steven D'Aprano

On Tue, 20 Mar 2007 10:28:10 +0100, Bruno Desthuilliers wrote:

[deploying weapons of mass snippage]
Your opinion. Too bad you're missing some of the most powerful parts of
the language.

Yes, it is my opinion, and it seems that in your zeal to defend new-style
classes against an imaginary attack, you've completely misunderstood what
my opinion is.

I'm not against new-style classes. I do use new-style classes. There are a
whole lot of extra features that new-style classes have that old-style
classes don't have, some of which I didn't even think of. (Thanks for
pointing them out, and I'm not being sarcastic.)

There are plenty of reasons for preferring new style classes. If those
reasons hold for you, then of course you should use new style classes.

But that's not the same thing as saying that you should use new style
classes *even when you don't care about those features*.

I never once suggested that new style classes are unnecessary, or a waste
of time, or bad, or whatever else you seem to think I was saying. My point
was, if you don't _need_ a new style class, there is no reason to avoid
using an old style class. It is a purely personal choice.

There seems to be a misunderstanding that classic classes have been
depreciated. They certainly have not. We've been told that old style
classes will "eventually" disappear, "probably" in Python 3. That is not
the same thing at all. The docs are very careful to avoid saying that old
style classes are depreciated.

(See, for example http://docs.python.org/ref/node33.html)

What I predict is that under the hood, Python 3 will complete the job of
unifying types and classes. The distinction between classic classes and
new style classes will go away. All classes will behave the same, whether
you write "class X:" or "class X():" or "class X(object):" or whatever
syntax Python 3 uses for defining classes.
 
S

Steven D'Aprano

Almost everything.

That's rather an exaggeration, don't you think? They have methods, and
inheritance, and attributes, all the critical features of classes, and
work perfectly well even if they don't support the more advanced features.

Since new-style classes are backward compatible with old-style ones,

Then "almost everything" is wrong with new style classes too? *wink*

almost all the old-style classes documentation applies to new-style ones
as well. Everything else is quite well documented too:
http://www.python.org/doc/newstyle/

On that very page, the first sentence says:

"Unfortunately, new-style classes have not yet been integrated into
Python's standard documention."

complete with spelling mistake.

properties don't work. Period. Properties rely on the descriptor
protocol, which only works with new-style classes.

Non-data descriptors (e.g. properties with only a getter) work fine. It is
only data descriptors (those with both a getter and a setter) that don't
work correctly.

- no metaclasses

Metaclasses worked all the way back in Python 1.5, although they were
painful and brain-exploding.

http://www.python.org/doc/essays/metaclasses

- no classmethod

Guido's own documentation for classmethods and staticmethods uses classic
classes. See

http://www.python.org/download/releases/2.2.3/descrintro/#staticmethods

But don't just take his word for it, try it for yourself *wink*
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top