Need help with Python class idioms

T

Tad Marko

Howdy!

I'm trying to get my head around Python and I've come to realize that
there are a lot of idioms in Python that are a bit different than in
other languages. I have a class similar to what I've included below.
The only difference is that in the real class, I have even more
mandatory attributes. Too many to specify at once on a constructor and
they don't always exist at construction time anyway, so the accessor
idiom must remain.

Can anyone suggest a more Pythony way to do the following?

Thanks,
Tad

#!/bin/env python

class A:
def __init__(self):
self.mandatoryVar1 = None
self.mandatoryVar2 = None

def setMV1(self, mv1):
self.mandatoryVar1 = mv1

def setMV2(self, mv2):
self.mandatoryVar2 = mv2

def saveToDB(self, db):
if self.mandatoryVar1 == None:
raise Exception, "Mandatory Var 1 not set."
if self.mandatoryVar2 == None:
raise Exception, "Mandatory Var 2 not set."

# Using db, do whatever saving stuff is needed.
 
J

James Henderson

Howdy!

I'm trying to get my head around Python and I've come to realize that
there are a lot of idioms in Python that are a bit different than in
other languages. I have a class similar to what I've included below.
The only difference is that in the real class, I have even more
mandatory attributes. Too many to specify at once on a constructor and
they don't always exist at construction time anyway, so the accessor
idiom must remain.

Can anyone suggest a more Pythony way to do the following?

Thanks,
Tad

#!/bin/env python

class A:
def __init__(self):
self.mandatoryVar1 = None
self.mandatoryVar2 = None

def setMV1(self, mv1):
self.mandatoryVar1 = mv1

def setMV2(self, mv2):
self.mandatoryVar2 = mv2

def saveToDB(self, db):
if self.mandatoryVar1 == None:
raise Exception, "Mandatory Var 1 not set."
if self.mandatoryVar2 == None:
raise Exception, "Mandatory Var 2 not set."

# Using db, do whatever saving stuff is needed.

What about this:

class A:
def __init__(self, mandatoryVar1, mandatoryVar2):
self.mandatoryVar1 = mandatoryVar1
self.mandatoryVar2 = mandatoryVar2
 
A

A.Schmolck

Can anyone suggest a more Pythony way to do the following?

Thanks,
Tad

#!/bin/env python

class A:
def __init__(self):
self.mandatoryVar1 = None
self.mandatoryVar2 = None

def setMV1(self, mv1):
self.mandatoryVar1 = mv1

def setMV2(self, mv2):
self.mandatoryVar2 = mv2

def saveToDB(self, db):
if self.mandatoryVar1 == None:
raise Exception, "Mandatory Var 1 not set."
if self.mandatoryVar2 == None:
raise Exception, "Mandatory Var 2 not set."

# Using db, do whatever saving stuff is needed.

class A(object):
def saveToDB(self, db):
# Using db, do whatever saving stuff is needed.

'as
 
J

James Henderson

[Tad Marko]
P.S. Since you're asking about idiom, it would be more Pythonic to write:

if self.mandatoryVar1 is None:

using the identity test "is" rather than equality test "==", since there is
only one None.

James
 
J

Jonathan Daugherty

# P.S. Since you're asking about idiom, it would be more Pythonic to write:
#
# if self.mandatoryVar1 is None:
#
# using the identity test "is" rather than equality test "==", since there is
# only one None.

I'd write

if not self.mandatoryVar1:

but the first method works, too.

--

Jonathan Daugherty
http://www.cprogrammer.org

"It's a book about a Spanish guy called Manual, you should read it."
-- Dilbert
 
J

Josiah Carlson

On 21 Jan 2004 12:43:28 -0800
Howdy!

I'm trying to get my head around Python and I've come to realize that
there are a lot of idioms in Python that are a bit different than in
other languages. I have a class similar to what I've included below.
The only difference is that in the real class, I have even more
mandatory attributes. Too many to specify at once on a constructor and
they don't always exist at construction time anyway, so the accessor
idiom must remain.

Can anyone suggest a more Pythony way to do the following?

Thanks,
Tad

#!/bin/env python

class A:
def __init__(self):
self.mandatoryVar1 = None
self.mandatoryVar2 = None

def setMV1(self, mv1):
self.mandatoryVar1 = mv1

def setMV2(self, mv2):
self.mandatoryVar2 = mv2

def saveToDB(self, db):
if self.mandatoryVar1 == None:
raise Exception, "Mandatory Var 1 not set."
if self.mandatoryVar2 == None:
raise Exception, "Mandatory Var 2 not set."

# Using db, do whatever saving stuff is needed.


mandatoryvariables = dict(mandatoryvar1=mv1, mandatoryvar2=mv2...)
inst = A()
inst.__dict__.update(mandatoryvariables)

That should work for you.
- Josiah
 
M

Mike C. Fletcher

Tad said:
Howdy!

I'm trying to get my head around Python and I've come to realize that
there are a lot of idioms in Python that are a bit different than in
other languages. I have a class similar to what I've included below.
The only difference is that in the real class, I have even more
mandatory attributes. Too many to specify at once on a constructor and
they don't always exist at construction time anyway, so the accessor
idiom must remain.

Can anyone suggest a more Pythony way to do the following?
Note: shameless plug follows...

With basicproperty, it would look something like this:

class A( propertied.Propertied ):
mandatoryVar1 = common.IntegerProperty(
"mandatoryVar1", """Property that's mandatory 'cause we're cool""",
)
defaultVar1 = common.IntegerProperty(
"defaultVar1", """Property that's got a default value""",
defaultValue = 32,
)
defaultVar2 = common.StringProperty(
"defaultVar2", """Property that's got a default function instead""",
defaultFunction = lambda prop, client: client.__class__.__name__,
)

a = A( mandatoryVar1 = 3 )
a.defaultVar2
a.defaultVar1

however, you continue on to show you're using a database, so you'd
probably prefer something like pytable (which is built on top of
basicproperty, but uses database schemas to control the creation and
operation of the properties):

from pytable.schemabuilder import *
schema = table(
"my_table",
comment = """Table for storing whatevers""",
fields = (
field(
'mandatoryVar1', 'integer',0, # name, sql data-type, size
constraints = (
notNull(),
),
),
field(
'defaultVal1', 'integer',0, # name, sql data-type, size
defaultValue = 32, # sql default value
constraints = (
notNull(),
),
),
field(
'Var2', 'timestamptz',0, # name, sql data-type, size
defaultValue = '"timestamp"(\'now\'::text)', # sql default value
constraints = (
notNull(),
),
),
),
indices = (
index( primary=1, fields=('mandatoryVar1', 'defaultVal1')),
),
)

print schema.itemClass
help( schema.itemClass )

row = schema.itemClass( mandatoryVar1 = 33 )
row.insertQuery( my_db_connection ) # get one from pytable
row.mandatoryVar1 = 34
row.updateQuery( my_db_connection )
row.deleteQuery( my_db_connection )

BasicProperty:
http://basicproperty.sourceforge.net/
PyTable RDBMS Wrapper:
http://pytable.sourceforge.net/

In a more general sense, for DB operations, use a database wrapper
module, there's lots of them around. And even more generally,
properties are *very* good at describing (common) property-based systems
of objects such as you're apparently working with. Properties are new
with Python 2.2, so underused sometimes, but they are very good at
certain types of domain modelling.

Enjoy yourself,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/
 
J

James Henderson

# P.S. Since you're asking about idiom, it would be more Pythonic to write:
#
# if self.mandatoryVar1 is None:
#
# using the identity test "is" rather than equality test "==", since there
is # only one None.

I'd write

if not self.mandatoryVar1:

but the first method works, too.

Are you sure an empty sequence or zero aren't valid values? J.
 
P

Paul McGuire

Jonathan Daugherty said:
# P.S. Since you're asking about idiom, it would be more Pythonic to write:
#
# if self.mandatoryVar1 is None:
#
# using the identity test "is" rather than equality test "==", since there is
# only one None.

I'd write

if not self.mandatoryVar1:

but the first method works, too.

--

Jonathan Daugherty
http://www.cprogrammer.org

"It's a book about a Spanish guy called Manual, you should read it."
-- Dilbert

.... what if mandatoryVar1 was set to False?

-- Paul
 
J

Jonathan Daugherty

# ... what if mandatoryVar1 was set to False?

To all who have responded to me as such: of course, how one
treats the variable in a boolean context depends on what its
semantically "false" value is. You do the math; I just
provided a syntax alternative. :)

--

Jonathan Daugherty
http://www.cprogrammer.org

"It's a book about a Spanish guy called Manual, you should read it."
-- Dilbert
 
K

kbass

I am new to Python and would like to attempt to write to a CSV file. I have
reviewed the documentation at http://www.object-craft.com.au/projects/csv/
for the csv 1.0 module but I didn't see any information referring to writing
(oe creating) a CSV file with this module. Does this module have the
capability to write a CSV file? Thanks!

Kevin
 
S

Skip Montanaro

Kevin> I am new to Python and would like to attempt to write to a CSV
Kevin> file. I have reviewed the documentation at
Kevin> http://www.object-craft.com.au/projects/csv/ for the csv 1.0
Kevin> module but I didn't see any information referring to writing (oe
Kevin> creating) a CSV file with this module. Does this module have the
Kevin> capability to write a CSV file?

Yes, but you should upgrade to 2.3 (if you haven't already) and just use the
csv module which comes with it:

http://www.python.org/doc/current/lib/module-csv.html

Skip
 
J

James Henderson

It can get weird if you have to allow your caller to
optionally specify the value None:


class _MissingParam:
"An object that no-one else will have a valid use for."
...
def a_func (opt1=_MissingParam):
if opt1 is _MissingParam:
opt1 = default_calculation () # for instance
...


Regards. Mel.

In the original example (not by me) it was None that was being used as the
marker that the value had not been set - that's all.

The topic was Python idiom and None is the most often used marker that a value
has not been passed explicitly and the default value should be used. (Of
course, if the default value is immutable it can be used directly.) See:

http://www.python.org/doc/current/ref/function.html

You're talking about the case where None may be passed explicitly and should
not trigger the default. An even terser solution to this than yours is to
use an empty list, though any mutable type will do. You see this all over
the Zope code:

_marker = []

J.
 
K

kbass

----- Original Message -----
From: "Skip Montanaro" <[email protected]>
To: "kbass" <[email protected]>
Cc: "Python List" <[email protected]>
Sent: Wednesday, January 21, 2004 6:39 PM
Subject: Re: Python and writing a CSV file

Kevin> I am new to Python and would like to attempt to write to a CSV
Kevin> file. I have reviewed the documentation at
Kevin> http://www.object-craft.com.au/projects/csv/ for the csv 1.0
Kevin> module but I didn't see any information referring to writing (oe
Kevin> creating) a CSV file with this module. Does this module have the
Kevin> capability to write a CSV file?

Yes, but you should upgrade to 2.3 (if you haven't already) and just use the
csv module which comes with it:

http://www.python.org/doc/current/lib/module-csv.html

Skip

Thanks for responding. Currently we do not have Python 2.3 installed on our
server, is there another way to perform this task with another module or
without a module? Thanks!

Kevin
 
S

Skip Montanaro

Kevin> Thanks for responding. Currently we do not have Python 2.3
Kevin> installed on our server, is there another way to perform this
Kevin> task with another module or without a module? Thanks!

The Object Craft module does write CSV files. When we wrote the module
included with 2.3, we conciously tried to keep it compatible with 2.2, so
you might well be able to just download it and compile it with 2.2 like any
other third-party module. If that fails, let me know and I'll see if I
can't steer you in the right direction.

Failing all that, if your data is very well-behaved, you can write valid CSV
data quite easily. Given a list of lists like so:

data = [
[1, 2, 4, "My data"],
["abc", "def", "ghi"],
["234234234", 1.2e7, "!@##%^*"],
]

you should be able to write it to sys.stdout with something like (untested):

for row in data:
row = [str(e) for e in row]
print '"' + '","'.join(row) + '"'

Note that the data above doesn't include quotation marks in any of the
fields, the separator is always a comma, and all output will be fully
quoted. Also, it assumes you're on Windows where you'll automatically get
CRLF terminators.

You should be able to fairly easily extend the above code to handle those
situations.

Skip
 
E

engsol

Kevin> Thanks for responding. Currently we do not have Python 2.3
Kevin> installed on our server, is there another way to perform this
Kevin> task with another module or without a module? Thanks!

The Object Craft module does write CSV files. When we wrote the module
included with 2.3, we conciously tried to keep it compatible with 2.2, so
you might well be able to just download it and compile it with 2.2 like any
other third-party module. If that fails, let me know and I'll see if I
can't steer you in the right direction.

Failing all that, if your data is very well-behaved, you can write valid CSV
data quite easily. Given a list of lists like so:

data = [
[1, 2, 4, "My data"],
["abc", "def", "ghi"],
["234234234", 1.2e7, "!@##%^*"],
]

you should be able to write it to sys.stdout with something like (untested):

for row in data:
row = [str(e) for e in row]
print '"' + '","'.join(row) + '"'

Note that the data above doesn't include quotation marks in any of the
fields, the separator is always a comma, and all output will be fully
quoted. Also, it assumes you're on Windows where you'll automatically get
CRLF terminators.

You should be able to fairly easily extend the above code to handle those
situations.

Skip
Great timing!

I was about to post a question regarding CSV files.

I bread-boarded a small test script to learn how the csv thing works,
and it seems to work well.

The script is:

import csv

writer = csv.writer(file('csv_test.CSV', 'w'))

list_1 = ['a','b','c']
list_2 = ['d','e','f']
list_3 = list_1 + list_2

for ix in range(3):
print list_3
writer.writerow(list_3)

stdout reports:

['a', 'b', 'c', 'd', 'e', 'f']
['a', 'b', 'c', 'd', 'e', 'f']
['a', 'b', 'c', 'd', 'e', 'f']

but the csv file shows:

a,b,c,d,e,f

a,b,c,d,e,f

a,b,c,d,e,f

So the question is, where does the extra crlf in the csv file come
from? And how do I get rid of it?

Thanks,
Norm
 
S

Skip Montanaro

Norm> writer = csv.writer(file('csv_test.CSV', 'w'))
...
Norm> So the question is, where does the extra crlf in the csv file come
Norm> from? And how do I get rid of it?

Try opening the CSV file in binary mode:

writer = csv.writer(file('csv_test.CSV', 'wb'))

Skip
 
E

engsol

Norm> writer = csv.writer(file('csv_test.CSV', 'w'))
...
Norm> So the question is, where does the extra crlf in the csv file come
Norm> from? And how do I get rid of it?

Try opening the CSV file in binary mode:

writer = csv.writer(file('csv_test.CSV', 'wb'))

Skip

Thanks Skip....works like a charm!
Norm
 

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,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top