473,395 Members | 1,460 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

setattr question

Hello

I have the following code:

#### builder.py #########
class HtmlBuilder(object):

@staticmethod
def page(title=''):
return HtmlPage(title)

@staticmethod
def element(tag, text=None, **attribs):
return HtmlElement(tag, text, **attribs)

@staticmethod
def literal(text):
return HtmlLiteral(text)

class HtmlElementFactory(object):

def __init__(self):
for tag in ['li', 'ul']:
setattr( self, tag, HtmlBuilder.element(tag) )

#########################

and so I can do the following:

html = HtmlElementFactory()
ul = html.ul
ul.attrib['class'] = 'default'
for i in range(3):
li = html.li
li.text = 'ghfhj'
ul.append(li)
print ul.to_string()

but what I'd like to do is:

html = HtmlElementFactory()
ul = html.ul( class='default' )
for i in range(3):
ul.append( html.li( 'ghfhj' )
print ul.to_string()

ie. to pass along *args and **kwargs to the HtmlElement constructor.
Any suggestions? Or is there a better way to this kind of thing?

thanks

Gerard

Mar 2 '06 #1
10 1979
Gerard Flanagan wrote:
Hello

I have the following code:

#### builder.py #########
class HtmlBuilder(object):

@staticmethod
def page(title=''):
return HtmlPage(title)

@staticmethod
def element(tag, text=None, **attribs):
return HtmlElement(tag, text, **attribs)

@staticmethod
def literal(text):
return HtmlLiteral(text)
Je ne vois pas très bien à quoi sert cette classe (à moins bien sûr
qu'il y ait d'autre code). Pour ce que je vois là, pourquoi ne pas
appeler directement les classes HtmlPage, HtmlElement et HtmlLiteral ?

Err... I don't see the point of this class. Why not just calling the
HtmlPage|Element|Literal classes directly ?
class HtmlElementFactory(object):

def __init__(self):
for tag in ['li', 'ul']:
setattr( self, tag, HtmlBuilder.element(tag) )

#########################

and so I can do the following:

html = HtmlElementFactory()
ul = html.ul
ul.attrib['class'] = 'default'
for i in range(3):
li = html.li
li.text = 'ghfhj'
ul.append(li)
print ul.to_string()

but what I'd like to do is:

html = HtmlElementFactory()
ul = html.ul( class='default' )

for i in range(3):
ul.append( html.li( 'ghfhj' )
print ul.to_string()
'to_string' ?
Let's see... 'to_string', a class with only staticmethods in it...
You're coming from Java, aren't you ?-)

(if yes, google for "python is not java", it may be helpful)
ie. to pass along *args and **kwargs to the HtmlElement constructor.
Any suggestions?
yes : pass along *args and **kwargs to the HtmlElement constructor !-)

Or is there a better way to this kind of thing?


yes again : kiss (Keep It Simple Stupid)

There's not enough code to really grasp what you're trying to do, but
from what I see, I'd say you're having a bad case of arbitrary
overcomplexification.

What's wrong with:

# nb: class is a reserved word in Python
ul = HtmlElement('ul', css_class='default')
for i in range(3):
ul.append(HtmlElement('li', 'baaz%d' % i)

# nb2: use the __str__() method of HtmlElement
print str(ul)

Python's philosophy is to make simple things simple (don't worry,
there's still space for complex things -> descriptors, metaclasses etc).

HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 2 '06 #2
Gerard Flanagan wrote:
I have the following code:

#### builder.py #########
class HtmlBuilder(object):

@staticmethod
def page(title=''):
return HtmlPage(title)

@staticmethod
def element(tag, text=None, **attribs):
return HtmlElement(tag, text, **attribs)

@staticmethod
def literal(text):
return HtmlLiteral(text)


just curious, but what's the purpose of this class, and what gave
you the idea to structure your program in this way ?

</F>

Mar 2 '06 #3
bruno at modulix wrote:
Gerard Flanagan wrote:
Hello

I have the following code:

#### builder.py #########
class HtmlBuilder(object):

@staticmethod
def page(title=''):
return HtmlPage(title)

@staticmethod
def element(tag, text=None, **attribs):
return HtmlElement(tag, text, **attribs)

@staticmethod
def literal(text):
return HtmlLiteral(text)
Je ne vois pas très bien à quoi sert cette classe (à moins bien sûr
qu'il y ait d'autre code). Pour ce que je vois là, pourquoi ne pas
appeler directement les classes HtmlPage, HtmlElement et HtmlLiteral ?


C'est une vaine tentative d'appliquer "the Factory Pattern" ! J'ai eu
commence d'ecrire les classes 'ul(HtmlElement), li(HtmlElement), etc ',
et le but de 'HtmlElementFactory' etait d'eviter ceci (cela?). Il y a
une recette ici:

http://aspn.activestate.com/ASPN/Coo...n/Recipe/86900

mais il utilise 'apply', qui est...blah

I was trying to implement the factory pattern.
The recipe above uses 'apply' which is deprecated according to the
docs, and I suppose I was curious how to do the same sort of thing
without 'apply'.
Err... I don't see the point of this class. Why not just calling the
HtmlPage|Element|Literal classes directly ?
class HtmlElementFactory(object):

def __init__(self):
for tag in ['li', 'ul']:
setattr( self, tag, HtmlBuilder.element(tag) )

#########################

and so I can do the following:

html = HtmlElementFactory()
ul = html.ul
ul.attrib['class'] = 'default'
for i in range(3):
li = html.li
li.text = 'ghfhj'
ul.append(li)
print ul.to_string()

but what I'd like to do is:

html = HtmlElementFactory()
ul = html.ul( class='default' )

for i in range(3):
ul.append( html.li( 'ghfhj' )
print ul.to_string()


'to_string' ?
Let's see... 'to_string', a class with only staticmethods in it...
You're coming from Java, aren't you ?-)


Never been to Java in my life!
I don't know if I understand you, HtmlElement has a 'to_string' method
but no static methods:

class HtmlElement(list):

def __init__(self, tag, text=None, **attrib):
self.tag = tag
self.text = text
self.attrib = attrib

def write(self, writer):
writer.start(self.tag, self.attrib)
if self.text is not None:
writer.data(self.text)
for node in self:
node.write(writer)
writer.end()

def to_string(self):
out = StringIO()
writer = HtmlWriter(out)
self.write(writer)
ret = out.getvalue()
out.close()
return ret
(if yes, google for "python is not java", it may be helpful)
ie. to pass along *args and **kwargs to the HtmlElement constructor.
Any suggestions?
yes : pass along *args and **kwargs to the HtmlElement constructor !-)

Or is there a better way to this kind of thing?


yes again : kiss (Keep It Simple Stupid)

There's not enough code to really grasp what you're trying to do, but
from what I see, I'd say you're having a bad case of arbitrary
overcomplexification.


My code itself is just a learning project ( etant sans emploi a ce
moment, moi-meme...) and it is no doubt a bit 'over-egged' at the
minute, but it is a first attempt and I can always refactor later.
What's wrong with:

# nb: class is a reserved word in Python
ul = HtmlElement('ul', css_class='default')
for i in range(3):
ul.append(HtmlElement('li', 'baaz%d' % i)

# nb2: use the __str__() method of HtmlElement
print str(ul)

Python's philosophy is to make simple things simple (don't worry,
there's still space for complex things -> descriptors, metaclasses etc).

HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"


Merci bien pour votre reponse.

Gerard

Mar 2 '06 #4
Fredrik Lundh wrote:
Gerard Flanagan wrote:
I have the following code:

#### builder.py #########
class HtmlBuilder(object):

@staticmethod
def page(title=''):
return HtmlPage(title)

@staticmethod
def element(tag, text=None, **attribs):
return HtmlElement(tag, text, **attribs)

@staticmethod
def literal(text):
return HtmlLiteral(text)


just curious, but what's the purpose of this class, and what gave
you the idea to structure your program in this way ?

</F>


In my defense, I can only quote Albert Einstein: "If we knew what it
was we were doing, it would not be called research, would it?" I'm
writing a script to generate a few relatively static webpages and
upload them to a server, but it's as much a learning exercise as
anything else - I have no formal programming education. I thought the
Factory pattern would be appropriate here; the class you quote was a
first attempt and i knew it was undoubtedly the wrong approach, so
that's why i asked the group...

Gerard

Mar 2 '06 #5
Gerard Flanagan wrote:
http://aspn.activestate.com/ASPN/Coo...n/Recipe/86900

mais il utilise 'apply', qui est...blah

I was trying to implement the factory pattern.
The recipe above uses 'apply' which is deprecated according to the
docs, and I suppose I was curious how to do the same sort of thing
without 'apply'.


Apply has been replaced by 'extended call syntax', that is why it is
deprecated. Instead of
return apply(self._function,_args,_kargs)

write
return self._function(*_args, **_kargs)

Kent
Mar 3 '06 #6
bruno at modulix wrote:
(snip)
Je ne vois pas très bien à quoi sert cette classe (à moins bien sûr
qu'il y ait d'autre code). Pour ce que je vois là, pourquoi ne pas
appeler directement les classes HtmlPage, HtmlElement et HtmlLiteral ?

oops, sorry, forgot to remove this before posting :(
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 3 '06 #7
Gerard Flanagan wrote:
bruno at modulix wrote:
(snip french)
I was trying to implement the factory pattern.
The recipe above uses 'apply' which is deprecated according to the
docs, and I suppose I was curious how to do the same sort of thing
without 'apply'.
def fun(*args, **kwargs):
pass

def otherfun(*args, **kwargs):
fun(*args, **kwargs)
Err... I don't see the point of this class. Why not just calling the
HtmlPage|Element|Literal classes directly ?

(snip)
'to_string' ?
Let's see... 'to_string', a class with only staticmethods in it...
You're coming from Java, aren't you ?-)

Never been to Java in my life!


bad guess.
I don't know if I understand you, HtmlElement has a 'to_string' method
I don't know this HtmlElement class, nor where it comes from.
'to_string()' (or is it toString() ?) is javaish. The pythonic idiom for
this is implementing the __str__() method and calling str(obj) on the
obj (which will call obj.__str__()). Hence my (bad) guess about you
being a Javaer.
but no static methods:
Not the HtmlElement class, but the HtmlBuilder one. Here again, a class
defining only staticmethods is a pretty javaish idiom - in Python, we
just use good old functions !-) (in a separate module if you want a
separate namespace).
class HtmlElement(list):

def __init__(self, tag, text=None, **attrib):
self.tag = tag
self.text = text
self.attrib = attrib

def write(self, writer):
writer.start(self.tag, self.attrib)
if self.text is not None:
writer.data(self.text)
for node in self:
node.write(writer)
writer.end()

def to_string(self):
out = StringIO()
writer = HtmlWriter(out)
self.write(writer)
ret = out.getvalue()
out.close()
return ret

If it's your own code, you may want to rename this last method __str__().
ie. to pass along *args and **kwargs to the HtmlElement constructor.
Any suggestions?


yes : pass along *args and **kwargs to the HtmlElement constructor !-)

Or is there a better way to this kind of thing?


yes again : kiss (Keep It Simple Stupid)

There's not enough code to really grasp what you're trying to do, but
from what I see, I'd say you're having a bad case of arbitrary
overcomplexification.


My code itself is just a learning project ( etant sans emploi a ce
moment, moi-meme...) and it is no doubt a bit 'over-egged' at the
minute, but it is a first attempt and I can always refactor later.


My experience is that it's far easier to start simple and add
flexibility where needed than to simplify useless complexity. KISS,
yagni and all that kind of things...

Merci bien pour votre reponse.

You're welcome.

BTW, there's also a french speaking python newsgroup at fr.comp.lang.py.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 3 '06 #8
bruno at modulix wrote:
[...]

I don't know this HtmlElement class, nor where it comes from.
'to_string()' (or is it toString() ?) is javaish. The pythonic idiom for
this is implementing the __str__() method and calling str(obj) on the
obj (which will call obj.__str__()). Hence my (bad) guess about you
being a Javaer.

I've made this change, thanks. ( I had a year with C# so maybe that's
why I'm so idiomatically-challenged ! )
Not the HtmlElement class, but the HtmlBuilder one. Here again, a class
defining only staticmethods is a pretty javaish idiom - in Python, we
just use good old functions !-) (in a separate module if you want a
separate namespace).

But it's personal preference, no? The functions were kind of related
and meaningless outside the module they were declared - but I'll take
it on board, anyway.

[...]

My experience is that it's far easier to start simple and add
flexibility where needed than to simplify useless complexity. KISS,
yagni and all that kind of things...

yagni - I'd never heard that one!

I've ditched the factory class in any case:

http://gflanagan.net/site/python/htm...HtmlBuilder.py
(FWIW)

Merci bien pour votre reponse.

You're welcome.

BTW, there's also a french speaking python newsgroup at fr.comp.lang.py.


I wasn't aware of that, I'll have a lurk!

Thanks again.

Gerard
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"


Mar 3 '06 #9
Gerard Flanagan wrote:
bruno at modulix wrote:
[...]
I don't know this HtmlElement class, nor where it comes from.
'to_string()' (or is it toString() ?) is javaish. The pythonic idiom for
this is implementing the __str__() method and calling str(obj) on the
obj (which will call obj.__str__()). Hence my (bad) guess about you
being a Javaer.
I've made this change, thanks. ( I had a year with C# so maybe that's
why I'm so idiomatically-challenged ! )


Well, C# being somewhat inspired by Java...
Not the HtmlElement class, but the HtmlBuilder one. Here again, a class
defining only staticmethods is a pretty javaish idiom - in Python, we
just use good old functions !-) (in a separate module if you want a
separate namespace).

But it's personal preference, no?


Well, in Python, there are a lot of things that can be done the way you
like it, but are better done the idiomatic way. Python relies quite a
lot on conventions and idioms where other languages try to inforce
strict rules.
The functions were kind of related
and meaningless outside the module they were declared -
FWIW (and from the snippet I saw), these functions are useless even in
the module !-)

Unless you want to dynamically choose the concrete class at runtime
based on platform/settings/phase of the moon/whatnot (which seems not to
be te case in the snippet you posted), you don't need these functions,
just instanciating the concrete class is enough. Remember that Python
classes *are* factory already - and that you can freely replace a class
by any callable returning an instance, ie:

== before refactoring, directly instanciating concrete class ==
# myhtmlmodule.py
class HtmlElement(tag, *args, **kw):
# code here

# myclientmodule.py
from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')
== after refactoring, using a factory function ==
# myhtmlmodule.py
class _HtmlElement1(tag, *args, **kw):
# code here

class _HtmlElement2(tag, *args, **kw):
# other code here

# yes, it's now a function...
def HtmlElement(tag, *args, **kw):
if phase_of_the_moon():
klass = _HtmlElement1
else:
klass = _HtmlElement2
return klass(tag, *args, **kw)

# myclientmodule.py
# well... nothing changed here !-)
from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')
You could also do the trick with metaclass black magic, but what, KISS...
but I'll take
it on board, anyway.

[...]

My experience is that it's far easier to start simple and add
flexibility where needed than to simplify useless complexity. KISS,
yagni and all that kind of things...

yagni - I'd never heard that one!


You Aint Gonna Need It.

Code not written is the best code, so don't write code "just in case".
Python is usually dynamic enough to make refactoring easy (cf example above)
I've ditched the factory class in any case:

http://gflanagan.net/site/python/htm...HtmlBuilder.py
(FWIW)


Seems mostly clean. May I suggest a couple small corrections/improvements ?

1/ potential bugfix:
try:
from tidy import parseString
except ImportError:
def parseString(text):
# woops, this function is supposed to return something
#pass
return text

2/ safer and cleaner
class HtmlPage(HtmlElement):
# removed class vars,
# replaced with default in __init__
def __init__(self, title, **kw):
self.title = title
self.stylesheets = kw.get('stylesheets', [])
self.doctype = kw.get('doctype', HTML4_STRICT)

BTW, there's also a french speaking python newsgroup at fr.comp.lang.py.


I wasn't aware of that, I'll have a lurk!


see you there !-)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 3 '06 #10
bruno at modulix wrote:
Gerard Flanagan wrote:
The functions were kind of related
and meaningless outside the module they were declared -
FWIW (and from the snippet I saw), these functions are useless even in
the module !-)


ok, ok... :-)
Unless you want to dynamically choose the concrete class at runtime
based on platform/settings/phase of the moon/whatnot (which seems not to
be te case in the snippet you posted), you don't need these functions,
just instanciating the concrete class is enough. Remember that Python
classes *are* factory already - and that you can freely replace a class
by any callable returning an instance, ie:

== before refactoring, directly instanciating concrete class ==
# myhtmlmodule.py
class HtmlElement(tag, *args, **kw):
# code here

# myclientmodule.py
from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')
== after refactoring, using a factory function ==
# myhtmlmodule.py
class _HtmlElement1(tag, *args, **kw):
# code here

class _HtmlElement2(tag, *args, **kw):
# other code here

# yes, it's now a function...
def HtmlElement(tag, *args, **kw):
if phase_of_the_moon():
klass = _HtmlElement1
else:
klass = _HtmlElement2
return klass(tag, *args, **kw)

# myclientmodule.py
# well... nothing changed here !-)
from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')

ah, I'm getting it.
I've ditched the factory class in any case:

http://gflanagan.net/site/python/htm...HtmlBuilder.py
(FWIW)
Seems mostly clean. May I suggest a couple small corrections/improvements ?

1/ potential bugfix:
try:
from tidy import parseString
except ImportError:
def parseString(text):
# woops, this function is supposed to return something
#pass
return text

2/ safer and cleaner
class HtmlPage(HtmlElement):
# removed class vars,
# replaced with default in __init__
def __init__(self, title, **kw):
self.title = title
self.stylesheets = kw.get('stylesheets', [])
self.doctype = kw.get('doctype', HTML4_STRICT)


That's much better - thanks very much for taking the time, I'm a little
bit wiser!

regards

Gerard
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"


Mar 3 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Eric | last post by:
Slightly off topic, i know, but here goes: I'm trying to xlate a module of mine to C++. Only problem is, it makes heavy use of "setattr". Anyone know a straightforward way to do "setattr" in C++...
4
by: Gerson Kurz | last post by:
I stumbled across this (while using my homebrewn enum class): class test: pass instance = test() setattr(instance, "THIS :*2+~# IS OBVIOUSLY INVALID", 123) I would've expected some kind of...
5
by: kramb64 | last post by:
I'm trying to use setattr inside a module. From outside a module it's easy: import spam name="hello" value=1 setattr(spam, name, value) But if I want to do this inside the module spam...
4
by: Alex | last post by:
I apologize for asking maybe a very trivial question. I have a new class object A with slots. One of the slots is, for example, object spam. Object spam, in turn, also has slots and one of them...
10
by: Paulo da Silva | last post by:
Hi! In a class C, I may do setattr(C,'x',10). Is it possible to use getattr/setattr for variables not inside classes or something equivalent? I mean with the same result as exec("x=10"). ...
6
by: Donn Ingle | last post by:
Hi, Here's some code, it's broken: class Key( object ): def __init__(self): self.props = KeyProps() def __getattr__(self, v): return getattr( self.props,v ) def __setattr__(self,var,val):
4
by: Rotlaus | last post by:
2 weeks ago i asked for a etended getattr() which worked really fine, but now i would love to have a extended setattr() as well. Lets assume i have some classes: class A(object): def...
4
by: maestro | last post by:
Why are these functions there? Is it somehow more idiomatic to use than to do obj.field ? Is there something you can with them that you can't by obj.field reference?
5
by: Bojan Mihelac | last post by:
Hi all - when trying to set some dynamic attributes in class, for example: class A: for lang in : exec('title_%s = lang' % lang) #this work but is ugly # setattr(A, "title_%s" % lang, lang) #...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.