A properties and obj.__dict__ question

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

A properties and obj.__dict__ question

Glen Jarvis
I have a question that is hard to ask without involving code. I reduced my project down to a tiny test case (as follows).

As you see, the following code will work and access the variables within the class successfully. However, it's a cheat, using the internal attributes instead of the properties (as properties don't show in __dict__).

The objective is to have a large string with different fields. The fields happen to all be members of my class.  So, I could hard code things like this:

message = """
    Name: %s
    Address: %s
    %s, %s  %s
 """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}

But, as each of the items are properties of the class, I'd like to be more dynamic, like this:

message = """
    Name: %(obj.name)s
    Address: %(obj.address)s
    %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
 """ % obj

I can do this with normal attributes, like the following:

message = """
    Name: %(name)s
    Address: %(address)s
    %(city)s, %(state)s  %(postal_code)s
 """ % obj.__dict__

However, these attributes in my case are properties and don't show in the __dict__.

Here's a runnable piece of code to demonstrate:


=-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
class Piggie(object):
    def __init__(self):
        """A demo for a BayPIGgies question"""
        self._name = None
        self._address = None

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if isinstance(value, basestring):
            value = value.strip()
        self._name = value

    @property
    def address(self):
        return self._address

    @address.setter
    def address(self, value):
        if isinstance(value, basestring):
            value = value.strip()
        self._address = value

    def __unicode__(self):
        if self.name is None:
            return u"Nameless Person"
        else:
            return self.name
    __str__ = __unicode__


f = Piggie()
f.name = 'Glen'


message = """
    Obviously, this is silly for only two fields like this.

    But, it's a very reduced test case to demo a problem from a
    much larger project.

    Name: %(_name)s
    Address:  %(_address)s
 """ %  f.__dict__

print message
=-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-


This works, as the output below shows. However, only by accessing the internal attributes of the class directly, not using the property accessors. How can I do something like this, but with property accessors. Something like dir(f) or f.__property_dict__ that just has the properties. 

Run:


    Obviously, this is silly for only two fields like this.

    But, it's a very reduced test case to demo a problem from a
    much larger project.

    Name: Glen
    Address:  None



Run with the properties used:

Traceback (most recent call last):
  File "x.py", line 48, in <module>
    """ %  f.__dict__
KeyError: 'name'
 

Thanks, for letting me share :)



Glen
--
Things which matter most must never be at the mercy of things which matter least.

-- Goethe

_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Dirk Bergstrom-5
I think that String.format will solve this for you, based on this
example from the python docs:

 >>> class Point(object):
...     def __init__(self, x, y):
...         self.x, self.y = x, y
...     def __str__(self):
...         return 'Point({self.x}, {self.y})'.format(self=self)

Found here:

http://docs.python.org/library/string.html#formatexamples

On 09/08/2011 08:51 PM, Glen Jarvis wrote:

> I have a question that is hard to ask without involving code. I reduced my
> project down to a tiny test case (as follows).
>
> As you see, the following code will work and access the variables within the
> class successfully. However, it's a cheat, using the internal attributes
> instead of the properties (as properties don't show in __dict__).
>
> The objective is to have a large string with different fields. The fields
> happen to all be members of my class.  So, I could hard code things like
> this:
>
> message = """
>      Name: %s
>      Address: %s
>      %s, %s  %s
>   """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
>
> But, as each of the items are properties of the class, I'd like to be more
> dynamic, like this:
>
> message = """
>      Name: %(obj.name)s
>      Address: %(obj.address)s
>      %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
>   """ % obj
>
> I can do this with normal attributes, like the following:
>
> message = """
>      Name: %(name)s
>      Address: %(address)s
>      %(city)s, %(state)s  %(postal_code)s
>   """ % obj.__dict__
>
> However, these attributes in my case are properties and don't show in the
> __dict__.
>
> Here's a runnable piece of code to demonstrate:
>
>
> =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
> class Piggie(object):
>      def __init__(self):
>          """A demo for a BayPIGgies question"""
>          self._name = None
>          self._address = None
>
>      @property
>      def name(self):
>          return self._name
>
>      @name.setter
>      def name(self, value):
>          if isinstance(value, basestring):
>              value = value.strip()
>          self._name = value
>
>      @property
>      def address(self):
>          return self._address
>
>      @address.setter
>      def address(self, value):
>          if isinstance(value, basestring):
>              value = value.strip()
>          self._address = value
>
>      def __unicode__(self):
>          if self.name is None:
>              return u"Nameless Person"
>          else:
>              return self.name
>      __str__ = __unicode__
>
>
> f = Piggie()
> f.name = 'Glen'
>
>
> message = """
>      Obviously, this is silly for only two fields like this.
>
>      But, it's a very reduced test case to demo a problem from a
>      much larger project.
>
>      Name: %(_name)s
>      Address:  %(_address)s
>   """ %  f.__dict__
>
> print message
> =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
>
>
> This works, as the output below shows. However, only by accessing the
> internal attributes of the class directly, not using the property accessors.
> How can I do something like this, but with property accessors. Something
> like dir(f) or f.__property_dict__ that just has the properties.
>
> Run:
>
>
>      Obviously, this is silly for only two fields like this.
>
>      But, it's a very reduced test case to demo a problem from a
>      much larger project.
>
>      Name: Glen
>      Address:  None
>
>
>
> Run with the properties used:
>
> Traceback (most recent call last):
>    File "x.py", line 48, in<module>
>      """ %  f.__dict__
> KeyError: 'name'
>
>
> Thanks, for letting me share :)
>
>
>
> Glen
>
>
>
> _______________________________________________
> Baypiggies mailing list
> [hidden email]
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies


--
        --------------------------------------
       Dirk Bergstrom           [hidden email]
              http://otisbean.com/
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Mark Voorhies
In reply to this post by Glen Jarvis
On Thursday, September 08, 2011 08:51:05 pm Glen Jarvis wrote:

> I have a question that is hard to ask without involving code. I reduced my
> project down to a tiny test case (as follows).
>
> As you see, the following code will work and access the variables within the
> class successfully. However, it's a cheat, using the internal attributes
> instead of the properties (as properties don't show in __dict__).
>
> The objective is to have a large string with different fields. The fields
> happen to all be members of my class.  So, I could hard code things like
> this:
>
> message = """
>     Name: %s
>     Address: %s
>     %s, %s  %s
>  """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
>
> But, as each of the items are properties of the class, I'd like to be more
> dynamic, like this:
>
> message = """
>     Name: %(obj.name)s
>     Address: %(obj.address)s
>     %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
>  """ % obj
>
> I can do this with normal attributes, like the following:
>
> message = """
>     Name: %(name)s
>     Address: %(address)s
>     %(city)s, %(state)s  %(postal_code)s
>  """ % obj.__dict__
>
> However, these attributes in my case are properties and don't show in the
> __dict__.
>
> Here's a runnable piece of code to demonstrate:
>
>
> =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
> class Piggie(object):
>     def __init__(self):
>         """A demo for a BayPIGgies question"""
>         self._name = None
>         self._address = None
>
>     @property
>     def name(self):
>         return self._name
>
>     @name.setter
>     def name(self, value):
>         if isinstance(value, basestring):
>             value = value.strip()
>         self._name = value
>
>     @property
>     def address(self):
>         return self._address
>
>     @address.setter
>     def address(self, value):
>         if isinstance(value, basestring):
>             value = value.strip()
>         self._address = value
>
>     def __unicode__(self):
>         if self.name is None:
>             return u"Nameless Person"
>         else:
>             return self.name
>     __str__ = __unicode__
>
>
> f = Piggie()
> f.name = 'Glen'
>
>
> message = """
>     Obviously, this is silly for only two fields like this.
>
>     But, it's a very reduced test case to demo a problem from a
>     much larger project.
>
>     Name: %(_name)s
>     Address:  %(_address)s
>  """ %  f.__dict__
>
> print message
> =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
>
>
> This works, as the output below shows. However, only by accessing the
> internal attributes of the class directly, not using the property accessors.
> How can I do something like this, but with property accessors. Something
> like dir(f) or f.__property_dict__ that just has the properties.
>
> Run:
>
>
>     Obviously, this is silly for only two fields like this.
>
>     But, it's a very reduced test case to demo a problem from a
>     much larger project.
>
>     Name: Glen
>     Address:  None
>
>
>
> Run with the properties used:
>
> Traceback (most recent call last):
>   File "x.py", line 48, in <module>
>     """ %  f.__dict__
> KeyError: 'name'
>
>
> Thanks, for letting me share :)
>
>
>
> Glen
>

What about:

message = """
     Name: %(obj.name)s
     Address: %(obj.address)s
     %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
  """ % dict((i,getattr(obj,i)) for i in dir(obj))

?

(obviously, this is dangerous if any attribute of obj has side effects)

If this is a string to be modified at run time, would it be reasonable
to just use eval or have the client supply an importable module?
(i.e., if you want dynamic behavior, can you take advantage of the
 fact that Python is already a dynamic language?)

--Mark
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Mark Voorhies
On Thursday, September 08, 2011 09:18:44 pm Mark Voorhies wrote:

> On Thursday, September 08, 2011 08:51:05 pm Glen Jarvis wrote:
> > I have a question that is hard to ask without involving code. I reduced my
> > project down to a tiny test case (as follows).
> >
> > As you see, the following code will work and access the variables within the
> > class successfully. However, it's a cheat, using the internal attributes
> > instead of the properties (as properties don't show in __dict__).
> >
> > The objective is to have a large string with different fields. The fields
> > happen to all be members of my class.  So, I could hard code things like
> > this:
> >
> > message = """
> >     Name: %s
> >     Address: %s
> >     %s, %s  %s
> >  """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
> >
> > But, as each of the items are properties of the class, I'd like to be more
> > dynamic, like this:
> >
> > message = """
> >     Name: %(obj.name)s
> >     Address: %(obj.address)s
> >     %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
> >  """ % obj
> >
> > I can do this with normal attributes, like the following:
> >
> > message = """
> >     Name: %(name)s
> >     Address: %(address)s
> >     %(city)s, %(state)s  %(postal_code)s
> >  """ % obj.__dict__
> >
> > However, these attributes in my case are properties and don't show in the
> > __dict__.
> >
> > Here's a runnable piece of code to demonstrate:
> >
> >
> > =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
> > class Piggie(object):
> >     def __init__(self):
> >         """A demo for a BayPIGgies question"""
> >         self._name = None
> >         self._address = None
> >
> >     @property
> >     def name(self):
> >         return self._name
> >
> >     @name.setter
> >     def name(self, value):
> >         if isinstance(value, basestring):
> >             value = value.strip()
> >         self._name = value
> >
> >     @property
> >     def address(self):
> >         return self._address
> >
> >     @address.setter
> >     def address(self, value):
> >         if isinstance(value, basestring):
> >             value = value.strip()
> >         self._address = value
> >
> >     def __unicode__(self):
> >         if self.name is None:
> >             return u"Nameless Person"
> >         else:
> >             return self.name
> >     __str__ = __unicode__
> >
> >
> > f = Piggie()
> > f.name = 'Glen'
> >
> >
> > message = """
> >     Obviously, this is silly for only two fields like this.
> >
> >     But, it's a very reduced test case to demo a problem from a
> >     much larger project.
> >
> >     Name: %(_name)s
> >     Address:  %(_address)s
> >  """ %  f.__dict__
> >
> > print message
> > =-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
> >
> >
> > This works, as the output below shows. However, only by accessing the
> > internal attributes of the class directly, not using the property accessors.
> > How can I do something like this, but with property accessors. Something
> > like dir(f) or f.__property_dict__ that just has the properties.
> >
> > Run:
> >
> >
> >     Obviously, this is silly for only two fields like this.
> >
> >     But, it's a very reduced test case to demo a problem from a
> >     much larger project.
> >
> >     Name: Glen
> >     Address:  None
> >
> >
> >
> > Run with the properties used:
> >
> > Traceback (most recent call last):
> >   File "x.py", line 48, in <module>
> >     """ %  f.__dict__
> > KeyError: 'name'
> >
> >
> > Thanks, for letting me share :)
> >
> >
> >
> > Glen
> >
>
> What about:
>
> message = """
>      Name: %(obj.name)s
>      Address: %(obj.address)s
>      %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
>   """ % dict((i,getattr(obj,i)) for i in dir(obj))
>
> ?
>
> (obviously, this is dangerous if any attribute of obj has side effects)
>
> If this is a string to be modified at run time, would it be reasonable
> to just use eval or have the client supply an importable module?
> (i.e., if you want dynamic behavior, can you take advantage of the
>  fact that Python is already a dynamic language?)
>
> --Mark
>

oops -- that code snippet should have been:
 message = """
      Name: %(name)s
      Address: %(address)s
      %(city)s, %(state)s  %(postal_code)s
   """ % dict((i,getattr(obj,i)) for i in dir(obj))

--Mark
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Simeon Franklin
In reply to this post by Glen Jarvis
Sounds like a job for the inspect module. I don't have a great deal of familiarity here so others may have better suggestions but given a toy class:

class foo(object):
    @property
    def x(self):
        return 1

I can use inspect to get all the attributes and values of objects of class with

>>> import inspect
>>> f = foo()
>>>dict(inspect.getmembers(f)) # returns a list of two tuples that I pass to dict
{'__class__': <class '__main__.foo'>,
 '__delattr__': <method-wrapper '__delattr__' of foo object at 0xa021f4c>,
 '__dict__': {},
... snip ...
 'x': 1}

You could use this dict in your format strings if you know that all properties are side-effect free. Alternatively if you need a more sophisticated method you could copy the __dict__ of your object and then add to it by calling inspect.classify_class_attrs on your class (not the instance) and noting that properties are identified in the resulting list of attribute objects. You could then call each one and add its name and value to your copy of obj.__dict__.

Hmm - this still has you calling all the properties beforehand and seems clunky. Aha! Try adding a __getitem__ method to your class like:


class foo(object):
    @property
    def x(self):
        return 1

    def __getitem__(self, key):
        return getattr(self, key)

And then your class emulates dictionary access (for item retrieval at least) so that

>>> f = foo()
>>> f['x'] # dict access
1
>>> "%(x)s" % f # and string formatting with named labels as a consequence
'1'

-regards
Simeon Franklin
<a href="tel:209%20846-2151" value="+12098462151" target="_blank">209 846-2151


_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Monte Davidoff
In reply to this post by Dirk Bergstrom-5
On 9/8/11 9:01 PM, Dirk Bergstrom wrote:
> I think that String.format will solve this for you, based on this
> example from the python docs:
>
> >>> class Point(object):
> ...     def __init__(self, x, y):
> ...         self.x, self.y = x, y
> ...     def __str__(self):
> ...         return 'Point({self.x}, {self.y})'.format(self=self)

Yes, for Glen's example, this works:

message = """
     Name: {0.name}
     Address: {0.address}
""".format(f)

Monte
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Eric Walstad-2
In reply to this post by Glen Jarvis

Hey Glen

I was working on something similar the other day and came up with a class that might work for you here.  The class is derived from dict and sets it's __dict__ to self

http://pastebin.com/tk7sa7tz

Hth

Eric

On Sep 8, 2011 8:51 PM, "Glen Jarvis" <[hidden email]> wrote:
> I have a question that is hard to ask without involving code. I reduced my
> project down to a tiny test case (as follows).
>
> As you see, the following code will work and access the variables within the
> class successfully. However, it's a cheat, using the internal attributes
> instead of the properties (as properties don't show in __dict__).
>
> The objective is to have a large string with different fields. The fields
> happen to all be members of my class. So, I could hard code things like
> this:
>
> message = """
> Name: %s
> Address: %s
> %s, %s %s
> """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
>
> But, as each of the items are properties of the class, I'd like to be more
> dynamic, like this:
>
> message = """
> Name: %(obj.name)s
> Address: %(obj.address)s
> %(obj.city)s, %(obj.state)s %(obj.postal_code)s
> """ % obj
>
> I can do this with normal attributes, like the following:
>
> message = """
> Name: %(name)s
> Address: %(address)s
> %(city)s, %(state)s %(postal_code)s
> """ % obj.__dict__
>
> However, these attributes in my case are properties and don't show in the
> __dict__.
>
> Here's a runnable piece of code to demonstrate:
>
>
> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
> class Piggie(object):
> def __init__(self):
> """A demo for a BayPIGgies question"""
> self._name = None
> self._address = None
>
> @property
> def name(self):
> return self._name
>
> @name.setter
> def name(self, value):
> if isinstance(value, basestring):
> value = value.strip()
> self._name = value
>
> @property
> def address(self):
> return self._address
>
> @address.setter
> def address(self, value):
> if isinstance(value, basestring):
> value = value.strip()
> self._address = value
>
> def __unicode__(self):
> if self.name is None:
> return u"Nameless Person"
> else:
> return self.name
> __str__ = __unicode__
>
>
> f = Piggie()
> f.name = 'Glen'
>
>
> message = """
> Obviously, this is silly for only two fields like this.
>
> But, it's a very reduced test case to demo a problem from a
> much larger project.
>
> Name: %(_name)s
> Address: %(_address)s
> """ % f.__dict__
>
> print message
> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
>
>
> This works, as the output below shows. However, only by accessing the
> internal attributes of the class directly, not using the property accessors.
> How can I do something like this, but with property accessors. Something
> like dir(f) or f.__property_dict__ that just has the properties.
>
> Run:
>
>
> Obviously, this is silly for only two fields like this.
>
> But, it's a very reduced test case to demo a problem from a
> much larger project.
>
> Name: Glen
> Address: None
>
>
>
> Run with the properties used:
>
> Traceback (most recent call last):
> File "x.py", line 48, in <module>
> """ % f.__dict__

> KeyError: 'name'
>
>
> Thanks, for letting me share :)
>
>
>
> Glen
> --
> Things which matter most must never be at the mercy of things which matter
> least.
>
> -- Goethe

_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Eric Walstad-2
And now that I'm in front of a computer, an example:

>>> class Classtionary(dict):
...     def __init__(self, **kwargs):
...         self.__dict__ = self
...         self.update(kwargs)
>>> message = """
...     Name: %(name)s
...     Address: %(address)s
...     %(city)s, %(state)s  %(postal_code)s
...  """
>>>
>>> data = Classtionary(
...     name="Glen",
...     address="123 Your Street",
...     city="San Francisco",
...     state="CA",
...     postal_code="94131"
... )
>>> print(message % data)

    Name: Glen
    Address: 123 Your Street
    San Francisco, CA  94131


Best,

Eric.
On Thu, Sep 8, 2011 at 10:08 PM, Eric Walstad <[hidden email]> wrote:

> Hey Glen
>
> I was working on something similar the other day and came up with a class
> that might work for you here.  The class is derived from dict and sets it's
> __dict__ to self
>
> http://pastebin.com/tk7sa7tz
>
> Hth
>
> Eric
>
> On Sep 8, 2011 8:51 PM, "Glen Jarvis" <[hidden email]> wrote:
>> I have a question that is hard to ask without involving code. I reduced my
>> project down to a tiny test case (as follows).
>>
>> As you see, the following code will work and access the variables within
>> the
>> class successfully. However, it's a cheat, using the internal attributes
>> instead of the properties (as properties don't show in __dict__).
>>
>> The objective is to have a large string with different fields. The fields
>> happen to all be members of my class. So, I could hard code things like
>> this:
>>
>> message = """
>> Name: %s
>> Address: %s
>> %s, %s %s
>> """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
>>
>> But, as each of the items are properties of the class, I'd like to be more
>> dynamic, like this:
>>
>> message = """
>> Name: %(obj.name)s
>> Address: %(obj.address)s
>> %(obj.city)s, %(obj.state)s %(obj.postal_code)s
>> """ % obj
>>
>> I can do this with normal attributes, like the following:
>>
>> message = """
>> Name: %(name)s
>> Address: %(address)s
>> %(city)s, %(state)s %(postal_code)s
>> """ % obj.__dict__
>>
>> However, these attributes in my case are properties and don't show in the
>> __dict__.
>>
>> Here's a runnable piece of code to demonstrate:
>>
>>
>> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
>> class Piggie(object):
>> def __init__(self):
>> """A demo for a BayPIGgies question"""
>> self._name = None
>> self._address = None
>>
>> @property
>> def name(self):
>> return self._name
>>
>> @name.setter
>> def name(self, value):
>> if isinstance(value, basestring):
>> value = value.strip()
>> self._name = value
>>
>> @property
>> def address(self):
>> return self._address
>>
>> @address.setter
>> def address(self, value):
>> if isinstance(value, basestring):
>> value = value.strip()
>> self._address = value
>>
>> def __unicode__(self):
>> if self.name is None:
>> return u"Nameless Person"
>> else:
>> return self.name
>> __str__ = __unicode__
>>
>>
>> f = Piggie()
>> f.name = 'Glen'
>>
>>
>> message = """
>> Obviously, this is silly for only two fields like this.
>>
>> But, it's a very reduced test case to demo a problem from a
>> much larger project.
>>
>> Name: %(_name)s
>> Address: %(_address)s
>> """ % f.__dict__
>>
>> print message
>> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
>>
>>
>> This works, as the output below shows. However, only by accessing the
>> internal attributes of the class directly, not using the property
>> accessors.
>> How can I do something like this, but with property accessors. Something
>> like dir(f) or f.__property_dict__ that just has the properties.
>>
>> Run:
>>
>>
>> Obviously, this is silly for only two fields like this.
>>
>> But, it's a very reduced test case to demo a problem from a
>> much larger project.
>>
>> Name: Glen
>> Address: None
>>
>>
>>
>> Run with the properties used:
>>
>> Traceback (most recent call last):
>> File "x.py", line 48, in <module>
>> """ % f.__dict__
>> KeyError: 'name'
>>
>>
>> Thanks, for letting me share :)
>>
>>
>>
>> Glen
>> --
>> Things which matter most must never be at the mercy of things which matter
>> least.
>>
>> -- Goethe
>
_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Max Slimmer
In reply to this post by Eric Walstad-2
I found this code in python cookbook years ago and have been using it ever since, I added the update method.


#--------------------------------------------------------------------------#
# adict - (AtribDict) A dict whose items can also be accessed as           #
#  member variables .                                                      #
# >>> d = adict (a=1, b=2)                                               #
# >>> d['c'] = 3                                                         #
# >>> print d.a, d.b, d.c                                                #
# 1 2 3                                                                  #
# >>> d.b = 10                                                           #
# >>> print d['b']                                                       #
# 10                                                                     #
# 11                                                                     #
# # but be careful , it 's easy to hide methods                          #
# >>> print d.get('c')                                                   #
# 3                                                                      #
# >>> d['get'] = 4                                                       #
# >>> print d.get('a')                                                   #
# Traceback ( most recent call last ):                                   #
# TypeError : 'int ' object is not callable                              #
#--------------------------------------------------------------------------#
class adict( dict ):
def __init__ (self , *args , ** kwargs ):
dict.__init__(self , *args , ** kwargs )
self.__dict__ = self

def update(self, *args,**kwargs):
dict.update(self, *args, **kwargs)
self.__dict__ = self


Max Slimmer
eMail: [hidden email]



On Thu, Sep 8, 2011 at 10:08 PM, Eric Walstad <[hidden email]> wrote:

Hey Glen

I was working on something similar the other day and came up with a class that might work for you here.  The class is derived from dict and sets it's __dict__ to self

http://pastebin.com/tk7sa7tz

Hth

Eric

On Sep 8, 2011 8:51 PM, "Glen Jarvis" <[hidden email]> wrote:
> I have a question that is hard to ask without involving code. I reduced my
> project down to a tiny test case (as follows).
>
> As you see, the following code will work and access the variables within the
> class successfully. However, it's a cheat, using the internal attributes
> instead of the properties (as properties don't show in __dict__).
>
> The objective is to have a large string with different fields. The fields
> happen to all be members of my class. So, I could hard code things like
> this:
>
> message = """
> Name: %s
> Address: %s
> %s, %s %s
> """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}
>
> But, as each of the items are properties of the class, I'd like to be more
> dynamic, like this:
>
> message = """
> Name: %(obj.name)s
> Address: %(obj.address)s
> %(obj.city)s, %(obj.state)s %(obj.postal_code)s
> """ % obj
>
> I can do this with normal attributes, like the following:
>
> message = """
> Name: %(name)s
> Address: %(address)s
> %(city)s, %(state)s %(postal_code)s
> """ % obj.__dict__
>
> However, these attributes in my case are properties and don't show in the
> __dict__.
>
> Here's a runnable piece of code to demonstrate:
>
>
> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
> class Piggie(object):
> def __init__(self):
> """A demo for a BayPIGgies question"""
> self._name = None
> self._address = None
>
> @property
> def name(self):
> return self._name
>
> @name.setter
> def name(self, value):
> if isinstance(value, basestring):
> value = value.strip()
> self._name = value
>
> @property
> def address(self):
> return self._address
>
> @address.setter
> def address(self, value):
> if isinstance(value, basestring):
> value = value.strip()
> self._address = value
>
> def __unicode__(self):
> if self.name is None:
> return u"Nameless Person"
> else:
> return self.name
> __str__ = __unicode__
>
>
> f = Piggie()
> f.name = 'Glen'
>
>
> message = """
> Obviously, this is silly for only two fields like this.
>
> But, it's a very reduced test case to demo a problem from a
> much larger project.
>
> Name: %(_name)s
> Address: %(_address)s
> """ % f.__dict__
>
> print message
> =-=-=-=-=-=-=- Start of Working Code -=-=-=-=-=-=-=-=-=-
>
>
> This works, as the output below shows. However, only by accessing the
> internal attributes of the class directly, not using the property accessors.
> How can I do something like this, but with property accessors. Something
> like dir(f) or f.__property_dict__ that just has the properties.
>
> Run:
>
>
> Obviously, this is silly for only two fields like this.
>
> But, it's a very reduced test case to demo a problem from a
> much larger project.
>
> Name: Glen
> Address: None
>
>
>
> Run with the properties used:
>
> Traceback (most recent call last):
> File "x.py", line 48, in <module>
> """ % f.__dict__

> KeyError: 'name'
>
>
> Thanks, for letting me share :)
>
>
>
> Glen
> --
> Things which matter most must never be at the mercy of things which matter
> least.
>
> -- Goethe

_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies


_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies
Reply | Threaded
Open this post in threaded view
|

Re: A properties and obj.__dict__ question

Glen Jarvis
In reply to this post by Glen Jarvis
Thanks everyone! 

I went with the format example. It was exactly what I was looking for:


In fact, before I tried to look it up or before I asked for help, I was writing things like:

%({obj}.name)s

The format module makes it even cleaner. Python so fits in your brain, I love it. I also love that I learned about the format module now....  w00t!

Again, thanks for all the help everyone!



Glen



On Thu, Sep 8, 2011 at 8:51 PM, Glen Jarvis <[hidden email]> wrote:
I have a question that is hard to ask without involving code. I reduced my project down to a tiny test case (as follows).

As you see, the following code will work and access the variables within the class successfully. However, it's a cheat, using the internal attributes instead of the properties (as properties don't show in __dict__).

The objective is to have a large string with different fields. The fields happen to all be members of my class.  So, I could hard code things like this:

message = """
    Name: %s
    Address: %s
    %s, %s  %s
 """ % {obj.name, obj.address, obj.city, obj.state, obj.postal_code}

But, as each of the items are properties of the class, I'd like to be more dynamic, like this:

message = """
    Name: %(obj.name)s
    Address: %(obj.address)s
    %(obj.city)s, %(obj.state)s  %(obj.postal_code)s
 """ % obj

I can do this with normal attributes, like the following:

message = """
    Name: %(name)s
    Address: %(address)s
    %(city)s, %(state)s  %(postal_code)s
 """ % obj.__dict__

However, these attributes in my case are properties and don't show in the __dict__.

Here's a runnable piece of code to demonstrate:


=-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-
class Piggie(object):
    def __init__(self):
        """A demo for a BayPIGgies question"""
        self._name = None
        self._address = None

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if isinstance(value, basestring):
            value = value.strip()
        self._name = value

    @property
    def address(self):
        return self._address

    @address.setter
    def address(self, value):
        if isinstance(value, basestring):
            value = value.strip()
        self._address = value

    def __unicode__(self):
        if self.name is None:
            return u"Nameless Person"
        else:
            return self.name
    __str__ = __unicode__


f = Piggie()
f.name = 'Glen'


message = """
    Obviously, this is silly for only two fields like this.

    But, it's a very reduced test case to demo a problem from a
    much larger project.

    Name: %(_name)s
    Address:  %(_address)s
 """ %  f.__dict__

print message
=-=-=-=-=-=-=-  Start of Working Code -=-=-=-=-=-=-=-=-=-


This works, as the output below shows. However, only by accessing the internal attributes of the class directly, not using the property accessors. How can I do something like this, but with property accessors. Something like dir(f) or f.__property_dict__ that just has the properties. 

Run:


    Obviously, this is silly for only two fields like this.

    But, it's a very reduced test case to demo a problem from a
    much larger project.

    Name: Glen
    Address:  None



Run with the properties used:

Traceback (most recent call last):
  File "x.py", line 48, in <module>
    """ %  f.__dict__
KeyError: 'name'
 

Thanks, for letting me share :)



Glen
--
Things which matter most must never be at the mercy of things which matter least.

-- Goethe



--
Things which matter most must never be at the mercy of things which matter least.

-- Goethe

_______________________________________________
Baypiggies mailing list
[hidden email]
To change your subscription options or unsubscribe:
http://mail.python.org/mailman/listinfo/baypiggies