Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Dynamically creating properties?

Reply
Thread Tools

Dynamically creating properties?

 
 
Andy Dingley
Guest
Posts: n/a
 
      10-27-2011
I have some XML, with a variable and somewhat unknown structure. I'd
like to encapsulate this in a Python class and expose the text of the
elements within as properties.

How can I dynamically generate properties (or methods) and add them to
my class? I can easily produce a dictionary of the required element
names and their text values, but how do I create new properties at run
time?

Thanks,
 
Reply With Quote
 
 
 
 
John Gordon
Guest
Posts: n/a
 
      10-27-2011
In <(E-Mail Removed)> Andy Dingley <(E-Mail Removed)> writes:

> How can I dynamically generate properties (or methods) and add them to
> my class? I can easily produce a dictionary of the required element
> names and their text values, but how do I create new properties at run
> time?


You can set dynamic attributes on class objects without any special
processing at all. Just do it, like so:

class X(object):
pass

myx = X()

myx.color = 'red'
myx.food = 'french fries'
myx.lucky_number = 7

Or, if you don't know the attribute name beforehand:

setattr(myx, 'occupation', 'programmer')

For methods, use an existing method name (without the trailing parentheses)
as the attribute value, like so:

myx.method = float # assigns the built-in method float()

--
John Gordon A is for Amy, who fell down the stairs
http://www.velocityreviews.com/forums/(E-Mail Removed) B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

 
Reply With Quote
 
 
 
 
DevPlayer
Guest
Posts: n/a
 
      10-27-2011
On Oct 27, 3:59*pm, Andy Dingley <(E-Mail Removed)> wrote:
> I have some XML, with a variable and somewhat unknown structure. I'd
> like to encapsulate this in a Python class and expose the text of the
> elements within as properties.
>
> How can I dynamically generate properties (or methods) and add them to
> my class? *I can easily produce a dictionary of the required element
> names and their text values, but how do I create new properties at run
> time?
>
> Thanks,


class MyX(object):
pass
myx = myx()

xml_tag = parse( file.readline() )

# should be a valid python named-reference syntax,
# although any object that can be a valid dict key is allowed.
# generally valid python named reference would be the answer to
your question
attribute = validate( xml_tag )

# dynamicly named property
setattr( myx, attribute, property(get_func, set_func, del_func,
attr_doc) )

# "dynamicly named method"
# really should be a valid python named-reference syntax
myfunc_name = validate(myfunc_name)

def somefunc(x):
return x+x
# or
somefunc = lambda x: x + x

setattr( myx, myfunc_name, somefunc )


So beaware of:
# \\\\\\\\\\\\\\\\\\\\\\\\\
setattr(myx, '1', 'one')

myx.1
File "<input>", line 1
x.1
^
SyntaxError: invalid syntax

# \\\\\\\\\\\\\\\\\\\\\\\\\
x.'1'
File "<input>", line 1
x.'1'
^
SyntaxError: invalid syntax

# \\\\\\\\\\\\\\\\\\\\\\\\\
x.__dict__['1'] # returns
'one'

x.__dict__ # returns
{'1': 'one'}

So you should validate your variable names if you are getting them
from somewhere.

 
Reply With Quote
 
DevPlayer
Guest
Posts: n/a
 
      10-27-2011
Personally I like to use this function instead of a "try: except:"
because try-except will allow names like __metaclass__.

Remember, setattr(obj, attr_name, value) allows attr_name to be any
valid str().
For example: '!@kdafk11', or '1_1', '1e-20', '0.0', '*one', '\n%%',
etc.

def isvalid_named_reference( astring ):
# "varible name" is really a named_reference
# import string # would be cleaner

valid_first_char =
'_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV WXYZ'
valid_rest =
'_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL MNOPQRSTUVWXYZ'

# I think it's ok here for the rare type-check
# as unicode named-references are not allowed
if type(astring) is not str: return False

if len(astring) == 0: return False

if astring[0] not in valid_first_char: return False

for c in astring[1:]:
if c not in valid_rest: return False

# Python keywords not allowed as named references (variable names)
for astr in ['and', 'assert', 'break', 'class', 'continue',
'def', 'del', 'elif', 'else', 'except', 'exec',
'finally', 'for', 'from', 'global', 'if',
'import', 'in', 'is', 'lambda', 'not', 'or',
'pass', 'print', 'raise', 'return', 'try',
'while', 'yield',]:
if astring == astr: return False

# valid names but bad idea
if astring == '__builtins__': return None
if astring == '__metaclass__': return None
for astr in dir(__builtins__):
if astring == astr: return None # use None as a warning

# there might be more like __slots__, and other
# module level effecting special names like '__metaclass__'

return True

Also when using dynamically created "varible names" to check if your
objects have an attribute with that name already.
 
Reply With Quote
 
DevPlayer
Guest
Posts: n/a
 
      10-27-2011

At least one error:
change:
> for astr in dir(__builtins__):

to:
for astr in __builtins__.__dict__:
 
Reply With Quote
 
DevPlayer
Guest
Posts: n/a
 
      10-28-2011
Second error

def isvalid_named_reference( astring ):
# "varible name" is really a named_reference
import __builtin__ # add line


 
Reply With Quote
 
Lie Ryan
Guest
Posts: n/a
 
      10-28-2011
On 10/28/2011 08:48 AM, DevPlayer wrote:
> On Oct 27, 3:59 pm, Andy Dingley<(E-Mail Removed)> wrote:
>> I have some XML, with a variable and somewhat unknown structure. I'd
>> like to encapsulate this in a Python class and expose the text of the
>> elements within as properties.
>>
>> How can I dynamically generate properties (or methods) and add them to
>> my class? I can easily produce a dictionary of the required element
>> names and their text values, but how do I create new properties at run
>> time?
>>
>> Thanks,

>
> class MyX(object):
> pass
> myx = myx()
>
> xml_tag = parse( file.readline() )
>
> # should be a valid python named-reference syntax,
> # although any object that can be a valid dict key is allowed.
> # generally valid python named reference would be the answer to
> your question
> attribute = validate( xml_tag )
>
> # dynamicly named property
> setattr( myx, attribute, property(get_func, set_func, del_func,
> attr_doc) )
>
> # "dynamicly named method"
> # really should be a valid python named-reference syntax
> myfunc_name = validate(myfunc_name)
>
> def somefunc(x):
> return x+x
> # or
> somefunc = lambda x: x + x
>
> setattr( myx, myfunc_name, somefunc )
>
>
> So beaware of:
> # \\\\\\\\\\\\\\\\\\\\\\\\\
> setattr(myx, '1', 'one')
>
> myx.1
> File "<input>", line 1
> x.1
> ^
> SyntaxError: invalid syntax
>
> # \\\\\\\\\\\\\\\\\\\\\\\\\
> x.'1'
> File "<input>", line 1
> x.'1'
> ^
> SyntaxError: invalid syntax
>
> # \\\\\\\\\\\\\\\\\\\\\\\\\
> x.__dict__['1'] # returns
> 'one'
>
> x.__dict__ # returns
> {'1': 'one'}
>
> So you should validate your variable names if you are getting them
> from somewhere.


XML does not allow attribute names to start with a number, so I doubt
you need to worry about that. In addition, if you also need to
dynamically access attributes and you have zero control of the name, you
can use getattr().

 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      10-28-2011
On Thu, 27 Oct 2011 16:00:57 -0700, DevPlayer wrote:

> def isvalid_named_reference( astring ):
> # "varible name" is really a named_reference
> # import string # would be cleaner


I don't understand the comment about "variable name".

> valid_first_char =
> '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV WXYZ'
> valid_rest =
> '_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL MNOPQRSTUVWXYZ'


This would be better:

import string
valid_first_char = '_' + string.ascii_letters
valid_rest = string.digits + valid_first_char



> # I think it's ok here for the rare type-check
> # as unicode named-references are not allowed
> if type(astring) is not str: return False


In Python 3 they are:

http://www.python.org/dev/peps/pep-3131/


> if len(astring) == 0: return False
> if astring[0] not in valid_first_char: return False
> for c in astring[1:]:
> if c not in valid_rest: return False
>
> # Python keywords not allowed as named references (variable names)
> for astr in ['and', 'assert', 'break', 'class', 'continue',
> 'def', 'del', 'elif', 'else', 'except', 'exec',
> 'finally', 'for', 'from', 'global', 'if', 'import',
> 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print',
> 'raise', 'return', 'try', 'while', 'yield',]:
> if astring == astr: return False


You missed 'as' and 'with'. And 'nonlocal' in Python 3. Possibly others.

Try this instead:

from keywords import iskeyword
if iskeyword(astring): return False




--
Steven
 
Reply With Quote
 
DevPlayer
Guest
Posts: n/a
 
      10-30-2011
To be honest, I was hoping someone would have posted a link to a well
known and tested recipe. You'd think this function would be in the
standard library or a specific Exception tied directly with setattr()
and getattr() (and possibly __getattr__(), __getattribute__(),
__setattr__())

The main thing I wanted to point out though is when you start using
dynamically named references, there's more to it then just letting a
dynamic file define it.

If there's a way to reference a set of data, it really shouldn't be
with a "dynamically named reference" too often.

Databases are a good example. Perhaps this is a better way for
example: If you have a bunch of tables in your DB -is- it better to
get the table def and create a Python class with dynamically named
"fields"?

Or is it better to create a Table class with name attribute and a
Field class with a name attribute (named "name")

SO instead of :
field_name = xml_parse.get_next_field_name(xml_table_definition )
my_table = Table()
setattr(my_table, field_name,
empty_list_to_later_contain_field_data)

Perhaps:
field_name = xml_parse.get_next_field_name(xml_table_definition )
my_table = Table()
my_table.fields[field_name] =
empty_list_to_later_contain_field_data
# or
my_table.add_field( Field(field_name) )

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Affecting a dynamically created drop down from another dynamically created drop down. msimmons ASP .Net 0 07-16-2009 03:17 PM
Managing ViewState of a dynamically created Custom Composite Server Control -(where the original is also dynamically created) dickster ASP .Net Building Controls 0 12-08-2005 09:32 AM
Inserting Controls Dynamically - with Validators Also Added Dynamically Jeffrey Todd ASP .Net 1 06-02-2005 04:33 PM
Load User Control Dynamically, Cast object dynamically =?Utf-8?B?UmV6YSBOYWJp?= ASP .Net 1 03-05-2005 12:04 AM
Load User Control Dynamically, Cast object dynamically =?Utf-8?B?UmV6YSBOYWJp?= ASP .Net 1 03-04-2005 07:57 PM



Advertisments