[Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?
Cameron Simpson
cs at zip.com.au
Sat Jan 23 18:28:30 EST 2016
On 23Jan2016 12:55, boB Stepp <robertvstepp at gmail.com> wrote:
>On Sat, Jan 23, 2016 at 3:30 AM, Cameron Simpson <cs at zip.com.au> wrote:
>> On 23Jan2016 01:52, boB Stepp <robertvstepp at gmail.com> wrote:
>>> I guess no matter how new one is to OOP, one nevertheless brings one's
>>> preconceptions, however malformed, into the learning process. In my
>>> case, one of mine was that once a class is coded, any given instance
>>> of a class is forevermore responsible for managing its *internals*, so
>>> that any change in these would be managed by the object when one of
>>> its (meant to be) publicly available methods is called.
>>
>> That is the pure OO way; and you can do things that way in Python, though
>> you can't _prevent_ direct access. However, it isn't the common way with
>> Python; generally with a Python class there are public attributes with
>> ordinary names; outsiders can consult them but generally should not change
>> them unless the doco says that is ok...
>
>I'd like to focus on this last sentence. Are you suggesting that it
>is "better" programming practice to code the class so that it has its
>own publicly available methods to process its public attributes?
No, I'm suggesting that in a pure OO system, your only access to the internal
state of an object is via .get_thing() methods and the only way to set them is
via .set_thing(value) methods. In a system where outsiders cannot access
internal attributes, that provides a completely opaque layer where the object
mediates these actions to ensure correctness and where the internals are
invisible, allowing a complete change of implementation without breaking the
interface outsiders use.
>And
>that it is both good practice and Pythonic to allow outsiders to
>freely read public attributes as needed?
Generally yes. As the author of the class, you need to decide what should be
visible (meaning "not have a leading underscore"). Of course it is _all_
visible, but when you give something a "public" name you are quietly implying
to outsiders that this is stable, and future implementations will continue to
preserve it.
You can be totally conservative of course and give all the internal state ._*
names. But an object with no attributes is generally not as useful. Note that
there's a grey area here: plenty of objects have methods which return values:
class O(object):
def __init__(self, name):
self._name = name
def name(self):
return self._name
o = O("foo")
print(o.name())
so you can keep the state "private" while presenting useful information via
methods. By having .name be a function, you are free to reimplement the class
using anther mechanism and outsiders will not have to change how they use
things:
class O(object):
def __init__(self, name):
# make a row in a database associating our id with this name
db.set_name(id(self), name)
def name(self):
# fetch the name back out of the database
n = db.get_name_by_id(id(self))
return n
>>> I suspect there are probably better ways to do what I am trying to
>>> demonstrate [I am trying to use a dict to simulate adding new instance
>>> variables after the fact.],
>>
>> You're aware that most objects have a .__dict__ attribute containing the
>> attributes? It is a dict, btw. So:
>>
>> class O(object):
>> pass
>>
>> >>> o=O()
>> >>> o.x=1
>> >>> o.__dict__
>> {'x': 1}
>
>The book I am currently working through, "Python Crash Course",
>despite its title, is oriented towards beginners to programming. It
>does not cover dunder methods and attributes, other than __init__().
>I am aware from following this list and reading portions of other
>books, that they exist, but I have not gotten into the details of any
>of them. So rewriting my class to use .__dict__, I have gotten:
>
>>>> class Dog(object):
> def __init__(self, name, breed):
> self.name = name
> self.breed = breed
> self.number_legs = 4
> self.number_tails = 1
> self.number_eyes = 2
> def show_attributes(self):
> print("The object,", self.name, "has the following attributes:")
> for attribute_name, attribute_value in self.__dict__.items():
> print(attribute_name, "=", attribute_value)
>
>>>> our_dog = Dog('Copper', 'beagle')
>>>> our_dog.show_attributes()
>The object, Copper has the following attributes:
>number_tails = 1
>number_eyes = 2
>breed = beagle
>number_legs = 4
>name = Copper
>>>> our_dog.unique_marking = 'blue right eye' # Adding a new attribute from outside the class definition.
>>>> our_dog.show_attributes()
>The object, Copper has the following attributes:
>number_eyes = 2
>breed = beagle
>unique_marking = blue right eye
>number_tails = 1
>number_legs = 4
>name = Copper
>
>I have to say that this seems very simple and direct despite my
>initial reluctance to assign new attributes to an object from outside
>the class definition of that object.
Yes. No magic here, just exposed mechanism :-)
>I still would like to do this via a method, but I am currently stuck
>on how to replace ??? with the attribute name I would like to insert:
>
>class Dog(object):
> ...
>
> def add_attribute(self, attribute_name, attribute_value):
> self.??? = attribute_value
self.__dict__[attribute_name] = attribute_value
>If I write something like:
>
>unique_marking = 'blue right eye'
>our_dog.add_attribute(unique_marking, 'blue right eye)
>
>I cannot get ??? to be unique_marking. Instead, show_attributes()
>will give from .__dict__, 'attribute_name', instead of what I would
>like to replace it with, unique_marking. But I have not given up yet!
The name is a string, so:
our_dog.add_attribute('unique_marking', 'blue right eye')
> But since I am struggling to accomplish this, that argues (my
>ignorance of Python aside) strongly for the clear, simple, direct
>approach above that I did in my rewrite.
>
>> Alan will take you up on doing purer OO practices in Python.
>
>An inside joke? Jedi Master Alan, please instruct me in the Pythonic
>ways of OO purity!
No, but Alan has a far better handle on the concrete definitions of what is
purely OO practice and what is commonly mixed in. He is also a stronger
advocate of pure OO approaches than I.
Cheers,
Cameron Simpson <cs at zip.com.au>
More information about the Tutor
mailing list