From: Adam B. <ad...@po...> - 2002-07-28 23:08:19
|
Hallo, Recently I found that some PgXXX classes defined in PgSQL module lack some features I would expect because of the fact that they are wrappers around PostgreSQL basic data types. For example, PgNumeric class is a wrapper around "numeric" type, so it should behave like a Python number: it should be comparable to other numeric Python types and it should be usable as a logical value (false when zero and true when non-zero). However, PgNumeric values behave differently: they cannot be compared to other, non-PgNumeric, types/classes and they always are "true" in logical expressions despite of their real value. I found the patch on pyPgSQL site which solves the latter problem, but the first one still exists. IMHO the most annoying problem is that PgNumeric values cannot be compared to data values of other type, for example following expressions: PgNumeric('123.45') == None PgNumeric('123.45') > 100 raise exceptions instead of returning "false" or "true" (0 or 1). Of course, one can write: type(PgNumeric('123.45')) == type(None) but it is not so elegant and differs from what we can write for standard built-in Python types: 123.45 == None Especially comparing values to None is very popular in database applications as None represents NULL value, am I not right? :) Since I am going to write some new programs using pyPgSQL library, I think I could contribute a patch to PgSQL module, which would solve problems described above. However I would like to know: 1. if compatibility with Python < 2.1 should be kept (I would like to use new __lt__, __eq__ etc. method names instead of __cmp__), 2. if PgNumeric, PgInt8 and other wrappers around PostgreSQL numeric types should be comparable to each other or to standard Python numeric types (float, long, int) only. Regards, -- Adam Buraczewski <ad...@po...> * Linux registered user #165585 GCS/TW d- s-:+>+:- a- C+++(++++) UL++++$ P++ L++++ E++ W+ N++ o? K? w-- O M- V- PS+ !PE Y PGP+ t+ 5 X+ R tv- b+ DI? D G++ e+++>++++ h r+>++ y? |
From: Mark M. <mar...@mc...> - 2002-07-29 00:02:59
|
> but it is not so elegant and differs from what we can write for > standard built-in Python types: > > 123.45 == None Have you tried: 123.45 is None: I thought comparing to None via equality was bad form? // m |
From: Gerhard <ger...@gm...> - 2002-07-29 01:05:05
|
* Mark McEahern <mar...@mc...> [2002-07-28 19:02 -0500]: > > but it is not so elegant and differs from what we can write for > > standard built-in Python types: > > > > 123.45 == None > > Have you tried: > > 123.45 is None: > > I thought comparing to None via equality was bad form? Indeed. I learnt that in a thread you started on c.l.py. All comparisons to None using == are now gone since the 2.1 release, btw. Gerhard -- mail: gerhard <at> bigfoot <dot> de registered Linux user #64239 web: http://www.cs.fhm.edu/~ifw00065/ OpenPGP public key id AD24C930 public key fingerprint: 3FCC 8700 3012 0A9E B0C9 3667 814B 9CAA AD24 C930 reduce(lambda x,y:x+y,map(lambda x:chr(ord(x)^42),tuple('zS^BED\nX_FOY\x0b'))) |
From: Adam B. <ad...@po...> - 2002-07-29 08:58:56
|
On Mon, Jul 29, 2002 at 03:04:49AM +0200, Gerhard H=E4ring wrote: > > > 123.45 =3D=3D None > > 123.45 is None: > > I thought comparing to None via equality was bad form? > Indeed. I learnt that in a thread you started on c.l.py. All comparison= s > to None using =3D=3D are now gone since the 2.1 release, btw. OK, You're right. I am not subscribed to c.l.py, although after reading this above I think I should. :/ Indeed, "is" operator is much more suitable for this purpose and is faster. Now I see that my knowledge of Python isn't simply good enough -- there are still problems like this that can be solved in different ways, and my solutions are sometimes not the best ones. :( I used to write "x =3D=3D None" because I had read in Python manual that "most other types compare unequal unless they are the same object", so everything except None should not be equal to None. And it worked until pyPgSQL 2.1 which broke some my existing applications. And instead of looking into changelog, I assumed that this could be a lack of "standard" behaviour of PgNumeric. It was lame, I know now :)) Thanks a lot! --=20 Adam Buraczewski <ad...@po...> * Linux registered user #165585 GCS/TW d- s-:+>+:- a- C+++(++++) UL++++$ P++ L++++ E++ W+ N++ o? K? w-- O M- V- PS+ !PE Y PGP+ t+ 5 X+ R tv- b+ DI? D G++ e+++>++++ h r+>++ y? |
From: Gerhard <ger...@gm...> - 2002-07-29 01:23:31
|
* Adam Buraczewski <ad...@po...> [2002-07-29 00:46 +0200]: > Hallo, > > Recently I found that some PgXXX classes defined in PgSQL module lack > some features I would expect because of the fact that they are > wrappers around PostgreSQL basic data types. For example, PgNumeric > class is a wrapper around "numeric" type, so it should behave like a > Python number: it should be comparable to other numeric Python types > and it should be usable as a logical value (false when zero and true > when non-zero). However, PgNumeric values behave differently: they > cannot be compared to other, non-PgNumeric, types/classes and they > always are "true" in logical expressions despite of their real value. > I found the patch on pyPgSQL site which solves the latter problem, Committed now with the addition of __pos__ and __abs__ (for the + and abs unary "operators"). > but the first one still exists. Indeed. It's not obvious for me how to fix this, as I'm not very proficient with emulating numeric types. It _seems_ that you can get a lot further by just adding something like this at the start of PgNumeric's __coerce__ method: if not isinstance(other, PgNumeric): other = PgNumeric(str(other)) I have a gut feeling, however, that this isn't all that'll be involved for PgNumerics. That's why I haven't commited this, yet. > IMHO the most annoying problem is that PgNumeric values cannot be > compared to data values of other type, for example following > expressions: > > PgNumeric('123.45') == None Ouch! As has been said already, this isn't good practise. But I learnt it only relatively recently myself. The reason is that None is a singleton and singletons are best compared using "is". This avoids potential bugs, and is a lot faster. > [...] Especially comparing values to None is very popular in database > applications as None represents NULL value, am I not right? :) Yeah. That's why you should do it like in SQL and compare using the "is"-operator :) > Since I am going to write some new programs using pyPgSQL library, I > think I could contribute a patch to PgSQL module, which would solve > problems described above. However I would like to know: > > 1. if compatibility with Python < 2.1 should be kept (I would like to > use new __lt__, __eq__ etc. method names instead of __cmp__), I myself haven't used Python 2.0 for years, but it's probably a bad idea to break Python 2.0 compatibility in the pyPgSQL 2.x line at this point. If you'd like to contribute to the upcoming (not started yet) pyPgSQL 3.0 instead, you could even use all the cool Python 2.2-only features ;-) > 2. if PgNumeric, PgInt8 and other wrappers around PostgreSQL numeric > types should be comparable to each other or to standard Python numeric > types (float, long, int) only. IMO, they should be comparable to all numeric types. I just noticed that currently, they aren't. Gerhard -- mail: gerhard <at> bigfoot <dot> de registered Linux user #64239 web: http://www.cs.fhm.edu/~ifw00065/ OpenPGP public key id AD24C930 public key fingerprint: 3FCC 8700 3012 0A9E B0C9 3667 814B 9CAA AD24 C930 reduce(lambda x,y:x+y,map(lambda x:chr(ord(x)^42),tuple('zS^BED\nX_FOY\x0b'))) |
From: Adam B. <ad...@po...> - 2002-07-29 08:58:56
|
On Mon, Jul 29, 2002 at 03:23:12AM +0200, Gerhard H=E4ring wrote: > > I found the patch on pyPgSQL site which solves the latter problem, > Committed now with the addition of __pos__ and __abs__ (for the + and > abs unary "operators"). Great! I'll get it in a few minutes :) > > but the first one still exists. > Indeed. It's not obvious for me how to fix this, as I'm not very > proficient with emulating numeric types. It _seems_ that you can get a > lot further by just adding something like this at the start of > PgNumeric's __coerce__ method: >=20 > if not isinstance(other, PgNumeric): > other =3D PgNumeric(str(other)) >=20 > I have a gut feeling, however, that this isn't all that'll be involved > for PgNumerics. That's why I haven't commited this, yet. I'll try to read more about implementing numeric types in Python. I feel that the section "3.3.6 Emulating numeric types" of the manual does not answer all my questions, so I am going to look into some mathematical Python libraries as well. I'll write here about my findings. >=20 > > [...] Especially comparing values to None is very popular in database > > applications as None represents NULL value, am I not right? :) > Yeah. That's why you should do it like in SQL and compare using the > "is"-operator :) OK, now I understand this :) > > 1. if compatibility with Python < 2.1 should be kept (I would like to > > use new __lt__, __eq__ etc. method names instead of __cmp__), > I myself haven't used Python 2.0 for years, but it's probably a bad ide= a > to break Python 2.0 compatibility in the pyPgSQL 2.x line at this point. > If you'd like to contribute to the upcoming (not started yet) pyPgSQL 3= .0 > instead, you could even use all the cool Python 2.2-only features ;-) After some thinking I found that probably __cmp__ should be enough for PgNumeric and other types, so compatibility with Python 2.0 could be preserved. Unless my studies on mathematical libraries (above) would prove something different, but even in this case I can define both __cmp__ and __lt__ and the latter will be used by Python >=3D 2.1 automatically. > IMO, they should be comparable to all numeric types. I just noticed tha= t > currently, they aren't. That's clear. Thanks a lot for the answers! Regards, --=20 Adam Buraczewski <ad...@po...> * Linux registered user #165585 GCS/TW d- s-:+>+:- a- C+++(++++) UL++++$ P++ L++++ E++ W+ N++ o? K? w-- O M- V- PS+ !PE Y PGP+ t+ 5 X+ R tv- b+ DI? D G++ e+++>++++ h r+>++ y? |