473,804 Members | 1,974 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Parameter lists

Consider the following snippet of code:

=============== ===========

class Stats:
def __init__(self, speed, maxHp, armor, strength, attackSpeed, imagePath):
self.speed = speed
self.maxHp = maxHp
self.armor = armor
self.strength = strength
self.attackSpee d = attackSpeed
self.originalIm age = loadTexture(ima gePath)

=============== ===========

I little container for holding the stats for some rpg character or
something. Now, I dont like the looks of that code, there are many
function parameters to be sent in and if I were to add an attribute, i
would need to add it in three places. Add it to the function
parameters, add it to the class and assign it.

Is there a smoother way to do this? There usually is in python, hehe.
I recall when reading python tutorials that you could do something
like this:

foo(*list_of_pa rameters):

To send many parameters as a list or a tuple. Then I could assign them
like this:

class Stats:
def __init__(self, *li):
self.speed = li[0]
self.maxHp = li[1]
(...)

Or maybe there is an even niftier way that lets me iterate through
them? Hmm... but that may lead to that I need to store them in a way
that makes it cumbersome to access them later.

Any comments and/or suggestions are welcome! :)
Feb 4 '07 #1
5 1497
Mizipzor
I dont like the looks of that code, there are many
function parameters to be sent in and if I were to add an attribute, i
would need to add it in three places. Add it to the function
parameters, add it to the class and assign it.
Is there a smoother way to do this?
You may use something like this:

def selfassign(self , locals):
# Code from web.py http://webpy.org modified.
for key, value in locals.iteritem s():
if key != 'self':
setattr(self, key, value)

Generally used in __init__ methods, as:

def __init__(self, foo, bar, baz=1):
selfassign(self , locals())

You may use it as (untested):

class Stats:
def __init__(self, speed, maxHp, armor, strength, attackSpeed,
imagePath):
selfassign(self , locals())
self.originalIm age = loadTexture(ima gePath)
del self.imagePath

I don't like that del

Bye,
bearophile

Feb 4 '07 #2
Mizipzor <mi******@gmail .comwrote in
news:ma******** *************** *************** *@python.org:
Consider the following snippet of code:

=============== ===========

class Stats:
def __init__(self, speed, maxHp, armor, strength,
attackSpeed, imagePath):
self.speed = speed
self.maxHp = maxHp
self.armor = armor
self.strength = strength
self.attackSpee d = attackSpeed
self.originalIm age = loadTexture(ima gePath)

=============== ===========

I little container for holding the stats for some rpg character
or something. Now, I dont like the looks of that code, there are
many function parameters to be sent in and if I were to add an
attribute, i would need to add it in three places. Add it to the
function parameters, add it to the class and assign it.

Is there a smoother way to do this? There usually is in python,
hehe. I recall when reading python tutorials that you could do
something like this:

foo(*list_of_pa rameters):

To send many parameters as a list or a tuple. Then I could
assign them like this:

class Stats:
def __init__(self, *li):
self.speed = li[0]
self.maxHp = li[1]
(...)

Or maybe there is an even niftier way that lets me iterate
through them? Hmm... but that may lead to that I need to store
them in a way that makes it cumbersome to access them later.

Any comments and/or suggestions are welcome! :)
I often use something like this, based on a Martellibot posting:
>>class Stats(dict):
.... def __init__(self, *args, **kwds):
.... self.update(*ar gs)
.... self.update(kwd s)
.... def __setitem__(sel f, key, value):
.... return super(Stats, self).__setitem __(key, value)
.... def __getitem__(sel f, name):
.... try:
.... return super(Stats, self).__getitem __(name)
.... except KeyError:
.... return None
.... __getattr__ = __getitem__
.... __setattr__ = __setitem__
....
>>m = dict(a=1,b=22,c =(1,2,3))
p = Stats(m,x=4,y=[5,9,11])
p.y
[5, 9, 11]
>>p['y']
[5, 9, 11]

--
rzed
Feb 4 '07 #3
Mizipzor wrote:
class Stats:
def __init__(self, *li):
self.speed = li[0]
self.maxHp = li[1]
(...)

Or maybe there is an even niftier way that lets me iterate through
them?
Using keyword arguments instead of positional parameters makes this easy:
>>class Stats:
.... def __init__(self, **kw):
.... self.__dict__.u pdate(kw)
....
>>stats = Stats(speed=10, maxHp=100, armor='plate mail')
stats.speed
10
>>stats.maxHp
100
>>stats.armor
'plate mail'
Jeffrey
Feb 4 '07 #4
On Sun, 04 Feb 2007 17:45:04 +0100, Mizipzor wrote:
Consider the following snippet of code:

=============== ===========

class Stats:
def __init__(self, speed, maxHp, armor, strength, attackSpeed, imagePath):
self.speed = speed
self.maxHp = maxHp
self.armor = armor
self.strength = strength
self.attackSpee d = attackSpeed
self.originalIm age = loadTexture(ima gePath)

=============== ===========

I little container for holding the stats for some rpg character or
something. Now, I dont like the looks of that code, there are many
function parameters to be sent in and if I were to add an attribute, i
would need to add it in three places. Add it to the function
parameters, add it to the class and assign it.

Is there a smoother way to do this? There usually is in python, hehe.
There is no "right way" to handle the issue of initialising attributes.
The above way is very common, easy, self-documenting and doesn't have that
many disadvantages unless you have lots of parameters to deal with.

I recall when reading python tutorials that you could do something
like this:

foo(*list_of_pa rameters):

To send many parameters as a list or a tuple. Then I could assign them
like this:

class Stats:
def __init__(self, *li):
self.speed = li[0]
self.maxHp = li[1]
(...)

That's even worse.

Which is correct?

Stats(..., armour, stealth, ...)
Stats(..., stealth, armour, ...)

You have to read the code to find out. Not just the function definition,
but you actually have to read through all the assignments. Bad bad bad.

Or maybe there is an even niftier way that lets me iterate through
them? Hmm... but that may lead to that I need to store them in a way
that makes it cumbersome to access them later.

def __init__(self, **kwargs):
for key in kwargs:
if hasattr(self, key):
# key clashes with an existing method or attribute
raise ValueError("Att ribute clash for '%s'" % key)
self.__dict__.u pdate(kwargs)
=== Advantages ===

(1) you can create new attributes without changing any code;
(2) creating an instance is self-documenting:

Stats(armour="c hainmail", stealth=2, strength=4, ...)

(3) attributes can be added in any order;
(4) easy to modify the class so it inherits sensible defaults:

class Stats:
armour = "leather"
wisdom = 10
dexterity = 10
weapon = "sword"
def __init__(self, **kwargs):
for key in kwargs:
if self.__dict__.h as_key(key):
raise ValueError("Att ribute clash for '%s'" % key
self.__dict__.u pdate(kwargs)

=== Disadvantages ===

(1) You have to put in the attribute name, always:

Stats(armour="c hainmail", stealth=2, strength=4, ...) instead of
Stats("chainmai l", 2, 4, ...)

(2) Typos can cause strange bugs which are hard to find:

Stats(armour="c hainmail", stealth=2, stregnth=4, ...)

Now your character is unexpectedly strong because it inherits the default,
and you don't know why.

(3) Easy to break your class functionality:

Stats(name_that _clashes_with_a _method="someth ing else", ...)

If you've got lots of attributes, you're better off moving them to
something like a INI file and reading from that:

class Stats:
defaults = "C:/path/defaults.ini"
def __init__(self, filename=None, **kwargs):
if not filename:
filename = self.__class__. defaults
self.get_defaul ts(filename) # an exercise for the reader
for key in kwargs:
if not self.__dict__.h as_key(key):
raise ValueError("Unk nown attribute '%s' given" % key)
self.__dict__.u pdate(kwargs)

Notice that here I've changed from testing for attributes which clash to
testing for attributes which *don't* match a key in the INI file. Which is
the "best" behaviour, I leave up to you to decide.

--
Steven D'Aprano

Feb 5 '07 #5
Steven D'Aprano a écrit :
On Sun, 04 Feb 2007 17:45:04 +0100, Mizipzor wrote:

>>Consider the following snippet of code:

class Stats:
def __init__(self, speed, maxHp, armor, strength, attackSpeed,
imagePath):
> self.speed = speed
self.maxHp = maxHp
self.armor = armor
self.strength = strength
self.attackSpee d = attackSpeed
self.originalIm age = loadTexture(ima gePath)
I little container for holding the stats for some rpg character or
something. Now, I dont like the looks of that code, there are many
function parameters to be sent in and if I were to add an attribute, i
would need to add it in three places. Add it to the function
parameters, add it to the class and assign it.

Is there a smoother way to do this? There usually is in python, hehe.

(snip)
>
def __init__(self, **kwargs):
for key in kwargs:
if hasattr(self, key):
# key clashes with an existing method or attribute
raise ValueError("Att ribute clash for '%s'" % key)
self.__dict__.u pdate(kwargs)
=== Advantages ===
(snip)
>
=== Disadvantages ===
(snip)
(2) Typos can cause strange bugs which are hard to find:

Stats(armour="c hainmail", stealth=2, stregnth=4, ...)

Now your character is unexpectedly strong because it inherits the
default,
and you don't know why.
(3) Easy to break your class functionality:

Stats(name_that _clashes_with_a _method="someth ing else", ...)
How to overcome these two problem - just overcomplexifyi ng things a bit:

class StatsAttribute( object):
def __init__(self, default=None):
self._default = default
self._attrname = None # set by the StatType metaclass

def __get__(self, instance, cls):
if instance is None:
return self
return instance._stats .get(self._attr name, self._default)

def __set__(self, instance, value):
instance._stats[self._attrname] = value

class StatsType(type) :
def __init__(cls, name, bases, attribs):
super(StatsType , cls).__init__(n ame, bases, attribs)
statskeys = getattr(cls, '_statskeys', set())
for name, attrib in attribs.items() :
if isinstance(attr ib, StatsAttribute) :
# sets the name to be used to get/set
# values in the instance's _stats dict.
attrib._attrnam e = name
# and store it so we know this is
# an expected attribute name
statskeys.add(n ame)
cls._statskeys = statskeys

class Stats(object):
__metaclass__ = StatsType

def __init__(self, **stats):
self._stats = dict()
for name, value in stats.items():
if name not in self._statskeys :
# fixes disadvantage #2 : we won't have unexpected kw args
msg = "%s() got an unexpected keyword argument '%s'" \
% (self.__class__ .__name__, name)
raise TypeError(msg)
setattr(self, name, value)

# just a dummy object, I didn't like the
# idea of using strings litterals for things
# like armors or weapons... And after all,
# it's supposed to be overcomplexifie d, isn't it ?
class _dummy(object):
def __init__(self, **kw):
self._kw = kw

def __getattr__(sel f, name):
return self._kw[name]

class Leather(_dummy) : pass
class Sword(_dummy): pass
class FullPlate(_dumm y): pass
class MagicTwoHanded( _dummy): pass

# let's go:
class Warrior(Stats):
# fixes disatvantage 3 : we won't have name clash
strength = StatsAttribute( default=12)
armour = StatsAttribute( default=Leather ())
weapon = StatsAttribute( default=Sword() )

bigBill = Warrior(
strength=120,
armour=FullPlat e(),
weapon=MagicTwo Handed(bonus=20 )
)

try:
wontDo = Warrior(
sex_appeal = None
)
except Exception, e:
print "got : %s" % e
Did I won a MasterProgramme r (or at least a SeasonnedPro) award ?-)
http://sunsite.nus.sg/pub/humour/prog-evolve.html

Err... me go to bed now...
If you've got lots of attributes, you're better off moving them to
something like a INI file and reading from that:

class Stats:
defaults = "C:/path/defaults.ini"
def __init__(self, filename=None, **kwargs):
if not filename:
filename = self.__class__. defaults
self.get_defaul ts(filename) # an exercise for the reader
for key in kwargs:
if not self.__dict__.h as_key(key):
raise ValueError("Unk nown attribute '%s' given" % key)
self.__dict__.u pdate(kwargs)
And then allow for Python source code in the INI file (that will be used
to create methods) to specify behaviour ?-)

Ok, this time I really go to bed !-)

Feb 5 '07 #6

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

Similar topics

10
125464
by: Resant | last post by:
I have a query : Exec 'Select * From Receiving Where Code In (' + @pCode + ')' @pCode will contain more than one string parameter, eg : A1, A2, A3 How can i write that parameters, I try use : set @pCode='A1','A2','A3' but get an error : Incorrect syntax near ','
1
1545
by: Chuck | last post by:
I am writing a database program in C#. I have a situation when I type the '(' after typing a method call, VS goes into an infinite loop. I then have to exit VS. Has anyone else had any trouble with statement completion / parameter information? Here is a little more information. The problem code looks like this: CodeData.t_xxx.Addt_xxxRow... CodeData references a strongly typed dataset. The dataset is in an other
7
9572
by: Richard Grant | last post by:
Hi. In c/C++ i can pass the address of a subroutine to another subroutine as an actual parameter How do I do that in VB .NET What should be the syntax for a parameter to receive the address of a subroutine Let's say theres a sub that creates buttons and I want it to receive as a parameter the address of the sub that handles the OnClick event for the button being created How do I pass such a parameter Thanks in advance Richar
70
4083
by: py | last post by:
I have function which takes an argument. My code needs that argument to be an iterable (something i can loop over)...so I dont care if its a list, tuple, etc. So I need a way to make sure that the argument is an iterable before using it. I know I could do... def foo(inputVal): if isinstance(inputVal, (list, tuple)): for val in inputVal: # do stuff
12
4646
by: ArunDhaJ | last post by:
Hi Friends, Is it possible to pass a table as a parameter to a funtion. whos function declaration would look some thing like this.... ALTER FUNCTION TempFunction (@TempTable TABLE, @nPId INT) my problem is: i have to access a temporary table created in an SP in a function
1
1557
by: pankyy1982 | last post by:
Hi Friends, I am trying to run a perl script which some arguments and i m getting an error--- Can't exec "filetrans.pl": The parameter or environment lists are too long. Please provide me ur inputs on this.
4
2063
by: abir | last post by:
I am matching a template, and specializing based of a template, rather than a single class. The codes are like, template<template<typename T,typename Alloc = std::allocator<T> class pix{ }; template<> class pix<vector>{
6
1648
by: ManicQin | last post by:
I have two templated classes for example let's say: template <typename _T , class _Trait> class modifier { public: _T modify() { return _Trait::change(m_data);
2
1514
by: not_a_commie | last post by:
how many of you have ever had a function declaration like this: public abstract void DoSomething(double a, double b, double c, double d, bool force); that you wished could be declared like this: public abstract void DoSomething(double a, b, c, d, bool force); ?
2
13272
by: Kaushal | last post by:
#include <iostream> #include <boost/mpl/vector.hpp> #include <boost/mpl/find.hpp> using namespace std ; using namespace boost ; template <typename numericTypes> struct evalThis
0
9716
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10604
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10103
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7644
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6874
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5536
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5676
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3839
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3006
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.