Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #82509 > unrolled thread
| Started by | "Ivan Evstegneev" <webmailgroups@gmail.com> |
|---|---|
| First post | 2014-12-14 18:20 +0200 |
| Last post | 2014-12-15 21:13 +0200 |
| Articles | 8 — 4 participants |
Back to article view | Back to comp.lang.python
Classes - converting external function to class's method. "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-12-14 18:20 +0200
Re: Classes - converting external function to class's method. Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-12-15 04:28 +1100
RE: Classes - converting external function to class's method. "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-12-14 21:49 +0200
Re: Classes - converting external function to class's method. Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-12-15 00:15 +0100
Re: Classes - converting external function to class's method. Terry Reedy <tjreedy@udel.edu> - 2014-12-14 19:11 -0500
Re: Classes - converting external function to class's method. Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-12-15 01:32 +0100
Re: Classes - converting external function to class's method. Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-12-15 13:01 +1100
RE: Classes - converting external function to class's method. "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-12-15 21:13 +0200
| From | "Ivan Evstegneev" <webmailgroups@gmail.com> |
|---|---|
| Date | 2014-12-14 18:20 +0200 |
| Subject | Classes - converting external function to class's method. |
| Message-ID | <mailman.16949.1418574125.18130.python-list@python.org> |
Hello Everyone,
I have stuck a bit with this example(took this one from the book).
Here are a description steps of what I've done till now:
Step 1 - creating an empty namespace:
>>>class rec: pass
Step 2 - adding some attributes:
>>>rec.name = 'Bob'
>>>rec.age = 40
Step 3 - Creating an instance:
>>>x= rec()
Step 4 - write down external function:
>>>def uppername(obj):
return obj.name.upper()
Step 5 - applying this function on x:
>>>uppername(x)
'BOB'
Till this moment its Ok.
But:
Step 6 - Creating a class method:
>>>rec.method = uppername
Then using the "help" function I get (just checking what happened):
>>>help(rec)
class rec(builtins.object)
| Methods defined here:
|
| method = uppername(obj)
|
| ----------------------------------------------------------------------
|omitted text......
|------------------------------------------------------------------------
| Data and other attributes defined here:
|
| age = 40
|
| name = 'Bob'
Then the same about x:
>>>help(x)
class rec(builtins.object)
| Methods defined here:
|
| method = uppername(obj)
| -------------------------------------------------------------------
omitted text .....
|---------------------------------------------------------------------
The last check I've made:
>>> help(x.method)
Help on method uppername in module __main__:
uppername() method of __main__.rec instance
>>> help(rec.method)
Help on function uppername in module __main__:
uppername(obj)
and now to the Step 7 - using this new "method" on x:
>>>x.method()
'BOB'
>>>rec.method()
.....
.....
TypeError: uppername() missing 1 required positional argument: 'obj'
and then:
>>>rec.method(rec)
'BOB'
So my the question is: what is going on here? How this actually works?
According to the book's downside note:
****************************************************************************
******
In fact, this is one of the reasons the self argument must always be
explicit in Python methods-because
methods can be created as simple functions independent of a class, they need
to make the implied instance
argument explicit. They can be called as either functions or methods, and
Python can neither guess nor
assume that a simple function might eventually become a class's method. The
main reason for the explicit
self argument, though, is to make the meanings of names more obvious: names
not referenced through
self are simple variables mapped to scopes, while names referenced through
self with attribute notation
are obviously instance attributes.
****************************************************************************
*****
Keeping it in mind, I wrote this code:
>>> class myclass:
def __init__(self, value):
self.name = value
def myupper(self):
return self.name.upper()
And then:
>>> b = myclass('bob')
>>>b.myupper()
'BOB'
I made an assumption that this is what happens(roughly speaking) when I
write this:
>>>rec.method = uppername
Am I right? (close enough maybe?)
On the other hand, when I checked further:
>>>dir(x.method)
[........, '__self__',.......]
but
>>>dir(rec.method)
[.... list of method and '__self__' wasn't there.....]
I got a "bit" confused.
Why actually in instance "x"
>>>x.method()
can auto-assign an "x" to uppername() function argument, but it doesn't work
in a class "rec" itself?
So I need to write down an "obj" argument manually.
Why '__self__' exists only in instance "x"? (maybe because "rec", initially
was created as an empty class?)
How does a function "uppername()" looks like, when I apply it to "rec"
class, so it becomes a class's method?
So in such a case, when instance "x" receives an "update" it reads the new
method as I described above(I mean the code of "myclass")?
Thanks a lot in advance,
Ivan.
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-12-15 04:28 +1100 |
| Message-ID | <548dc8a1$0$12982$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #82509 |
Ivan Evstegneev wrote:
> Hello Everyone,
>
> I have stuck a bit with this example(took this one from the book).
The example you are working on (adding external functions as methods) is
actually a bit more complicated than it seems, as you have discovered. You
have this:
class rec: pass
rec.name = 'Bob'
rec.age = 40
x= rec()
def uppername(obj):
return obj.name.upper()
rec.method = uppername
This is almost equivalent to the following:
class rec:
name = 'Bob'
age = 40
def method(obj):
return obj.name.upper()
You then try to use this new method, by calling it from the instance:
x.method()
--> returns 'BOB' as you expected
In this case, it works as you expect. Python looks up "method" on the
instance, and doesn't find anything attached to the instance. It then looks
at the class "rec", which does have something called "method". Because this
is a function, Python knows to provide the instance x as the first
argument. So the call
x.method()
ends up turning into this:
rec.method(x)
Your function uppername() receives x as the argument "obj", it looks up
obj.name (x.name) and returns it as uppercase.
The important part to see here is that when you call a method from an
instance:
instance.method()
Python *automatically* fills in the "self" argument using the instance. (In
your case, you called that argument "obj" instead of self, but Python
doesn't care what it is called.)
How does Python know to use x as self? Because it's written right there:
x.method uses x as the first argument for method. But this is only done for
*instances*, not classes.
Now you move on to calling the method from the class itself:
rec.method()
--> raises TypeError
rec.method(rec)
--> returns 'BOB'
Looking at this, I can guess you are using Python 3, because that won't work
in Python 2. Am I right?
When you call a method from the class, Python cannot fill in the "self"
argument because it doesn't know what instance to use. This is called
an "unbound method" in Python 2, but in Python 3 it is just a regular
function.
The important thing here are these two rules:
* when you call a method from an instance, Python automatically binds
that instance to the first argument (usually called "self") of the
method:
instance.method() --> method gets instance as the "self" argument
* when you call a method from the class, Python cannot bind an
instance to "self", so you have to do it:
Class.method() --> no argument is given!
Class.method(instance) --> method gets instance as "self"
In your example, you didn't actually pass an instance, you just passed the
class itself:
rec.method(rec)
But that's okay, because in *this case* the class has a "name" attribute, so
it all works out alright. But normally this would fail.
The actual mechanism for how Python does this is called the descriptor
protocol, and if you look it up you can find some explanations for it, but
be warned that it is quite technical and it is only for very advanced work
that you need to care about it.
> Keeping it in mind, I wrote this code:
>
> class myclass:
> def __init__(self, value):
> self.name = value
> def myupper(self):
> return self.name.upper()
>
> And then:
>
> b = myclass('bob')
> b.myupper()
> 'BOB'
>
> I made an assumption that this is what happens(roughly speaking) when I
> write this:
>
> rec.method = uppername
>
> Am I right? (close enough maybe?)
Close enough.
> On the other hand, when I checked further:
>
>>>>dir(x.method)
> [........, '__self__',.......]
That is because you are looking the method up on the instance, x. If you
look it up on rec, there is no instance so Python cannot give it an
__self__ attribute.
> but
>>>>dir(rec.method)
> [.... list of method and '__self__' wasn't there.....]
Exactly!
You are looking at a complicated part of Object Oriented Programming, as
done by Python, so it is not surprising if it takes a while to understand
this. Please feel free to ask more questions if anything is unclear.
> I got a "bit" confused.
>
> Why actually in instance "x"
>>>>x.method()
> can auto-assign an "x" to uppername() function argument, but it doesn't
> work in a class "rec" itself?
When you have an instance
x.method
then Python knows which instance to use, because it is right there: x.
But if you have no instance, only the class:
rec.method
how does Python know which instance to use? There could be a million
instances, or none.
Let us look at some strings: the class is called "str", and we can have
many, many different instances:
"hello".upper()
--> returns "HELLO"
"goodbye".upper()
--> returns "GOODBYE"
But if I call the method from the class, which instance should it use?
str.upper()
???? return "HELLO" or "GOODBYE" or "1234" or "ABCD" or ... ????
The only way is for you to tell Python which instance to use:
str.upper("hello") # just like "hello".upper()
--> returns "HELLO"
> So I need to write down an "obj" argument manually.
> Why '__self__' exists only in instance "x"? (maybe because "rec",
> initially was created as an empty class?)
No. __self__ exists when you call the method from x, because __self__ is set
to x. If you call it from the class rec, there is no instance so __self__
cannot be set to an instance.
> How does a function "uppername()" looks like, when I apply it to "rec"
> class, so it becomes a class's method?
I don't understand this question.
> So in such a case, when instance "x" receives an "update" it reads the new
> method as I described above(I mean the code of "myclass")?
Or this question. Can you explain what you mean?
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | "Ivan Evstegneev" <webmailgroups@gmail.com> |
|---|---|
| Date | 2014-12-14 21:49 +0200 |
| Message-ID | <mailman.16958.1418594531.18130.python-list@python.org> |
| In reply to | #82519 |
[Multipart message — attachments visible in raw view] — view raw
Dear Steven,
I very appreciate your answer.
You just explained a lot of background things and you did it in more
explicit and simple way than it've appeared in the book.
I also agree with you about the fact that there are some advanced topics
spread within a book's text.
It is sometimes hard to a newbie to separate essential and from non
essential(I mean more advanced) topics.
So I may find myself digging down too much ^_^
In order to assemble the picture I would like to refer to couple of things
you mentioned:
>In this case, it works as you expect. Python looks up "method" on the
instance, and doesn't find anything attached to the instance. It then looks
at the class "rec",
>which does have something called "method". Because this is a function,
Python knows to provide the instance x as the first argument. So the call
> x.method()
>ends up turning into this:
>rec.method(x)
I saw something similar to this example, but initially didn't understand
what the author meant, so I skipped it ))))
Here is a quote from a book(Please see Pic1.jpg too):
***************************************
Method Calls
If this I2.w reference is a function call, what it really means is "call the
C3.w function to
process I2." That is, Python will automatically map the call I2.w() into the
call
C3.w(I2), passing in the instance as the first argument to the inherited
function.
***************************************
This was much confusing, till the moment I've read your explanation on live
example. )))
> Looking at this, I can guess you are using Python 3, because that won't
work in
> Python 2. Am I right?
Yes. I downloaded, Python 3.4 from python.org. Currently working with IDLE.
> The important part to see here is that when you call a method from an
> instance:
>
> instance.method()
>
> Python *automatically* fills in the "self" argument using the instance.
(In your
> case, you called that argument "obj" instead of self, but Python doesn't
care
> what it is called.)
>
> How does Python know to use x as self? Because it's written right there:
> x.method uses x as the first argument for method. But this is only done
for
> *instances*, not classes.
So, just to summarize all this stuff:
A class doesn't have method __self__ by itself.
I checked this on some other class provided in the book:
>>> class FirstClass: # Define a class object
def setdata(self, value): # Define class's methods
self.data = value # self is the instance
def display(self):
print(self.data)
And then check it with:
>>>dir(FirstClass)
[....Yep no __self__ here....]
On the other side, when an instance created, it does have __self__ method.
> > How does a function "uppername()" looks like, when I apply it to "rec"
> > class, so it becomes a class's method?
>
> I don't understand this question.
Well this is an embarrassing moment, it's just shows how lame my English can
be )))))
What I tried to ask here is if there any changes applied by Python to code
of function "uppername()" when it becomes class method (after using this
command: rec.method = uppername)
Never mind, you already answered it here:
> This is almost equivalent to the following:
>
> class rec:
> name = 'Bob'
> age = 40
> def method(obj):
> return obj.name.upper()
Moreover, regard to the "rec.method = uppername"
As I can understand, in this case Python does make some changes to the
function, but they are implicit.
Am I right?
Sincerely,
Ivan
> -----Original Message-----
> From: Python-list [mailto:python-list-
> bounces+webmailgroups=gmail.com@python.org] On Behalf Of Steven
> D'Aprano
> Sent: Sunday, December 14, 2014 19:28
> To: python-list@python.org
> Subject: Re: Classes - converting external function to class's method.
>
> Ivan Evstegneev wrote:
>
> > Hello Everyone,
> >
> > I have stuck a bit with this example(took this one from the book).
>
> The example you are working on (adding external functions as methods) is
> actually a bit more complicated than it seems, as you have discovered. You
have
> this:
>
> class rec: pass
> rec.name = 'Bob'
> rec.age = 40
>
> x= rec()
>
> def uppername(obj):
> return obj.name.upper()
>
> rec.method = uppername
>
>
> This is almost equivalent to the following:
>
> class rec:
> name = 'Bob'
> age = 40
> def method(obj):
> return obj.name.upper()
>
>
> You then try to use this new method, by calling it from the instance:
>
> x.method()
> --> returns 'BOB' as you expected
>
>
> In this case, it works as you expect. Python looks up "method" on the
instance,
> and doesn't find anything attached to the instance. It then looks at the
class
> "rec", which does have something called "method". Because this is a
function,
> Python knows to provide the instance x as the first argument. So the call
>
> x.method()
>
> ends up turning into this:
>
> rec.method(x)
>
> Your function uppername() receives x as the argument "obj", it looks up
> obj.name (x.name) and returns it as uppercase.
>
> The important part to see here is that when you call a method from an
> instance:
>
> instance.method()
>
> Python *automatically* fills in the "self" argument using the instance.
(In your
> case, you called that argument "obj" instead of self, but Python doesn't
care
> what it is called.)
>
> How does Python know to use x as self? Because it's written right there:
> x.method uses x as the first argument for method. But this is only done
for
> *instances*, not classes.
>
>
> Now you move on to calling the method from the class itself:
>
> rec.method()
> --> raises TypeError
>
> rec.method(rec)
> --> returns 'BOB'
>
> Looking at this, I can guess you are using Python 3, because that won't
work in
> Python 2. Am I right?
>
> When you call a method from the class, Python cannot fill in the "self"
> argument because it doesn't know what instance to use. This is called an
> "unbound method" in Python 2, but in Python 3 it is just a regular
function.
>
> The important thing here are these two rules:
>
> * when you call a method from an instance, Python automatically binds
> that instance to the first argument (usually called "self") of the
> method:
>
> instance.method() --> method gets instance as the "self" argument
>
> * when you call a method from the class, Python cannot bind an
> instance to "self", so you have to do it:
>
> Class.method() --> no argument is given!
>
> Class.method(instance) --> method gets instance as "self"
>
>
> In your example, you didn't actually pass an instance, you just passed the
class
> itself:
>
> rec.method(rec)
>
> But that's okay, because in *this case* the class has a "name" attribute,
so it all
> works out alright. But normally this would fail.
>
> The actual mechanism for how Python does this is called the descriptor
protocol,
> and if you look it up you can find some explanations for it, but be warned
that it
> is quite technical and it is only for very advanced work that you need to
care
> about it.
>
>
> > Keeping it in mind, I wrote this code:
> >
> > class myclass:
> > def __init__(self, value):
> > self.name = value
> > def myupper(self):
> > return self.name.upper()
> >
> > And then:
> >
> > b = myclass('bob')
> > b.myupper()
> > 'BOB'
> >
> > I made an assumption that this is what happens(roughly speaking) when
> > I write this:
> >
> > rec.method = uppername
> >
> > Am I right? (close enough maybe?)
>
> Close enough.
>
>
>
> > On the other hand, when I checked further:
> >
> >>>>dir(x.method)
> > [........, '__self__',.......]
>
> That is because you are looking the method up on the instance, x. If you
look it
> up on rec, there is no instance so Python cannot give it an __self__
attribute.
>
>
> > but
> >>>>dir(rec.method)
> > [.... list of method and '__self__' wasn't there.....]
>
> Exactly!
>
> You are looking at a complicated part of Object Oriented Programming, as
done
> by Python, so it is not surprising if it takes a while to understand this.
Please feel
> free to ask more questions if anything is unclear.
>
>
> > I got a "bit" confused.
> >
> > Why actually in instance "x"
> >>>>x.method()
> > can auto-assign an "x" to uppername() function argument, but it
> > doesn't work in a class "rec" itself?
>
> When you have an instance
>
> x.method
>
> then Python knows which instance to use, because it is right there: x.
>
> But if you have no instance, only the class:
>
> rec.method
>
> how does Python know which instance to use? There could be a million
> instances, or none.
>
> Let us look at some strings: the class is called "str", and we can have
many, many
> different instances:
>
> "hello".upper()
> --> returns "HELLO"
>
> "goodbye".upper()
> --> returns "GOODBYE"
>
>
> But if I call the method from the class, which instance should it use?
>
> str.upper()
> ???? return "HELLO" or "GOODBYE" or "1234" or "ABCD" or ... ????
>
> The only way is for you to tell Python which instance to use:
>
> str.upper("hello") # just like "hello".upper()
> --> returns "HELLO"
>
>
>
> > So I need to write down an "obj" argument manually.
> > Why '__self__' exists only in instance "x"? (maybe because "rec",
> > initially was created as an empty class?)
>
> No. __self__ exists when you call the method from x, because __self__ is
set to
> x. If you call it from the class rec, there is no instance so __self__
cannot be set
> to an instance.
>
>
> > How does a function "uppername()" looks like, when I apply it to "rec"
> > class, so it becomes a class's method?
>
> I don't understand this question.
>
>
> > So in such a case, when instance "x" receives an "update" it reads the
> > new method as I described above(I mean the code of "myclass")?
>
> Or this question. Can you explain what you mean?
>
>
>
>
> --
> Steven
>
> --
> https://mail.python.org/mailman/listinfo/python-list
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2014-12-15 00:15 +0100 |
| Message-ID | <2082416.uXDKvNnAXg@PointedEars.de> |
| In reply to | #82509 |
Ivan Evstegneev wrote:
> I have stuck a bit with this example(took this one from the book).
>
> Here are a description steps of what I've done till now:
>
>
> Step 1 - creating an empty namespace:
>
>>>>class rec: pass
IMHO that is not actually creating a namespace; it is just
declaring/defining an empty class.
The equivalent of a namespace in Python is a module; the file path starting
from an entry in the PYTHONPATH works like a namespace (the module is
considered to be in a package if the directory contains an __init__.py
file). (One can assume that this was derived from Java.)
BTW, the recommended Python 3.x way is
class Rec (object):
pass
(whereas “pass” is a placeholder statement, a bit like the yada-yada
operator of Python) and you should start class identifiers uppercase
(therefore, “Rec” instead) in order to avoid name collisions with built-in
class identifiers (“str”, “int” etc.) and make it easier to tell apart
instantiations from function/method calls. This recommendation applies to
other similar OOPLs too, but ISTM is especially important in Python code
where there is no “new” keyword used in instantiation.
> Step 4 - write down external function:
>
> >>>def uppername(obj):
> return obj.name.upper()
>
> […]
> Step 6 - Creating a class method:
>
>>>rec.method = uppername
> […]
>>>>x.method()
> 'BOB'
>
>>>>rec.method()
> .....
> .....
> TypeError: uppername() missing 1 required positional argument: 'obj'
>
> and then:
>
>>>>rec.method(rec)
> 'BOB'
>
> So my the question is: what is going on here? How this actually works?
Short answer: Calling rec.method(x) is equivalent to calling x.method() if
type(x) == rec.
| >>> class C (object): pass
| >>> def foo (self):
| ... print(self)
| >>> C.foo = foo
| >>> C.foo()
| Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| TypeError: foo() missing 1 required positional argument: 'self'
| >>> o = C()
| >>> C.foo(o)
| <__main__.C object at 0x7f64a7458be0>
| >>> o.foo()
| <__main__.C object at 0x7f64a7458be0>
Long answer:
If you call that method as the method of a class (object), you need to pass
an argument for the first parameter because you have made it positional, not
optional (it has no default value). If you pass (a reference to) the class
as first argument of that method, the class is the object whose attribute is
accessed. Classes are objects (this, too, was probably derived from Java).
(In fact, AFAIK almost everything is an object in Python; there are no
primitive data types at all.)
If instead you call that method as the method of an instance, the first
argument is a reference to that instance implicitly, so the signature of the
method is met implicitly and there is no error. (See below for an
explanation as to why “self.name” still works.) Any arguments that you pass
then in the argument list are passed as second, third aso. argument to the
method. To this method, then, you MUST NOT pass other arguments because it
does not take any more than already supplied implicitly.
[Fixed comb-quote; please keep to at most 80 characters per line, best 72]
> According to the book's downside note:
>
> ************************************************************************
> In fact, this is one of the reasons the self argument must always be
> explicit in Python methods-because methods can be created as simple
> functions independent of a class, they need to make the implied instance
> argument explicit. They can be called as either functions or methods,
> and Python can neither guess nor assume that a simple function might
> eventually become a class's method.
> The main reason for the explicit self argument, though, is to make the
> meanings of names more obvious: names not referenced through
> self are simple variables mapped to scopes, while names referenced
> through self with attribute notation are obviously instance attributes.
> ***********************************************************************
Exactly.
> Keeping it in mind, I wrote this code:
>
>>>> class myclass:
> def __init__(self, value):
> self.name = value
> def myupper(self):
> return self.name.upper()
>
> And then:
>
>>>> b = myclass('bob')
>>>>b.myupper()
> 'BOB'
>
> I made an assumption that this is what happens(roughly speaking) when I
> write this:
>
>>>>rec.method = uppername
>
> Am I right? (close enough maybe?)
Close, maybe. The difference is that in the original code the class has the
attribute and the instance merely inherits it, while in the code above only
the instance has the attribute.
IOW, in the code above the attribute (value) is not implicitly shared with
other instances of that class. And ISTM that with the original code it is
not possible to modify the attribute value except by accessing it directly
or through a method that is passed the reference to the *class* (because a
simple assignment in a method merely defines a local variable; there appears
to be no closure over class attributes).
Compare
,----
| >>> class C (object):
| ... foo = 42
| ... def bar (self):
| ... print(self.foo)
| ... self.foo = 23
| ...
| >>> C.foo
| 42
| >>> o = C()
| >>> o.foo
| 42
| >>> C.foo
| 42
| >>> o.bar()
| 42
| >>> o.foo
| 23
| >>> C.foo
| 42
`----
vs.
,----
| >>> class C2 (object):
| ... def __init__ (self):
| ... self.foo = 42
| ...
| >>> C2().foo
| 42
| >>> C2.foo
| Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| AttributeError: type object 'C2' has no attribute 'foo'
`----
> On the other hand, when I checked further:
>
>>>>dir(x.method)
> [........, '__self__',.......]
>
> but
>>>>dir(rec.method)
> [.... list of method and '__self__' wasn't there.....]
,----
| >>> print(dir.__doc__)
| dir([object]) -> list of strings
|
| If called without an argument, return the names in the current scope.
| Else, return an alphabetized list of names comprising (some of) the
| attributes of the given object, and of attributes reachable from it.
| If the object supplies a method named __dir__, it will be used; otherwise
| the default dir() logic is used and returns:
| for a module object: the module's attributes.
| for a class object: its attributes, and recursively the attributes
| of its bases.
| for any other object: its attributes, its class's attributes, and
^^^^^^^^^^^^^^^^^^^^
| recursively the attributes of its class's base classes.
`----
> I got a "bit" confused.
There is no good reason that “__self__” should be an attribute of a *class*
method or a *class*, so it most certainly is not. On the other hand, it
makes a lot of sense that a method of an instance has a way to refer to its
owner.
> Why actually in instance "x"
>>>>x.method()
> can auto-assign an "x" to uppername() function argument, but it doesn't
> work in a class "rec" itself?
Because classes and instances are not only different objects, but also
(instances) of different (classes/)types. It is the way Python OOP (in
fact, its entire type system) works:
| >>> class C (object): pass
| >>> type(C)
| <class 'type'>
| >>> type(C())
| <class '__main__.C'>
> So I need to write down an "obj" argument manually.
If you intend the function to be called as the method of an instance, you
would be well-advised to name the parameter “self”, as recommended. (Which
is probably derived from Smalltalk-80 and Self, some of the first OOPLs.)
> Why '__self__' exists only in instance "x"?
If I am not mistaken, you have not yet ascertained that the attribute
'__self__' exists in the instance at all, only that it exists as an
attribute of the *method* of an instance. In fact, I find:
| >>> '__self__' in dir(C())
| False
> (maybe because "rec", initially was created as an empty class?)
Unlikely. But you can simply test that.
> How does a function "uppername()" looks like, when I apply it to "rec"
> class, so it becomes a class's method?
> So in such a case, when instance "x" receives an "update" it reads the new
> method as I described above(I mean the code of "myclass")?
def uppername (self):
return self._name.upper()
and the like (BTDT). (It is recommended to start identifiers of
implementation-specific symbols, that should not be accessed from outside
the class, with “_” – PyDev then recognizes them as “protected”. Therefore,
“self._name” instead.)
(I prefer the space before the parameter list in declarations/definitions in
order to tell them apart easily from argument lists in calls/instantiations.
YMMV.)
> Thanks a lot in advance,
You’re welcome.
--
PointedEars
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2014-12-14 19:11 -0500 |
| Message-ID | <mailman.16964.1418602282.18130.python-list@python.org> |
| In reply to | #82531 |
On 12/14/2014 6:15 PM, Thomas 'PointedEars' Lahn wrote: > Ivan Evstegneev wrote: > >> I have stuck a bit with this example(took this one from the book). >> >> Here are a description steps of what I've done till now: >> >> >> Step 1 - creating an empty namespace: >> >>>>> class rec: pass > > IMHO that is not actually creating a namespace; it is just > declaring/defining an empty class. I pythonland, a namespace is a many to one mapping between names and objects. They are usually but not necessarily implemented with dicts. Some might restrict the term to a mapping with a .attribute interface for getting and setting. Others consider any string-key dict to be a namespace. The types module has a class SimpleNamespace. It has been proposed to move it to builtins with the name 'namespace'. > BTW, the recommended Python 3.x way is > > class Rec (object): > pass I hope you meant Python *2*.x, where '(object)' *is* needed to make a newstyle class. In 3.x, '(object)' is optional and normally omitted except in code meant to run unchanged in 2 and 3. -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2014-12-15 01:32 +0100 |
| Message-ID | <3517223.7xnpL0NDtR@PointedEars.de> |
| In reply to | #82536 |
Terry Reedy wrote: > On 12/14/2014 6:15 PM, Thomas 'PointedEars' Lahn wrote: >> Ivan Evstegneev wrote: >>> I have stuck a bit with this example(took this one from the book). >>> >>> Here are a description steps of what I've done till now: >>> >>> Step 1 - creating an empty namespace: >>> >>>>>> class rec: pass >> >> IMHO that is not actually creating a namespace; it is just >> declaring/defining an empty class. > > I pythonland, a namespace is a many to one mapping between names and > objects. They are usually but not necessarily implemented with dicts. > […] > >> BTW, the recommended Python 3.x way is >> >> class Rec (object): >> pass > > I hope you meant Python *2*.x, I did not. > where '(object)' *is* needed to make a newstyle class. In 3.x, '(object)' > is optional and normally omitted except in code meant to run unchanged in > 2 and 3. Your statements are corroborated by the Language Reference: <https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces> <https://docs.python.org/2.7/reference/datamodel.html#new-style-and-classic-classes> Thanks. -- PointedEars
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-12-15 13:01 +1100 |
| Message-ID | <548e40de$0$12997$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #82531 |
Thomas 'PointedEars' Lahn wrote: > Ivan Evstegneev wrote: > >> I have stuck a bit with this example(took this one from the book). >> >> Here are a description steps of what I've done till now: >> >> >> Step 1 - creating an empty namespace: >> >>>>>class rec: pass > > IMHO that is not actually creating a namespace; it is just > declaring/defining an empty class. And classes are namespaces. As are instances. One clue is the fact that we use exactly the same syntax for accessing names in a namespace regardless of whether the namespace is a package, a module, a class or an instance: import collections.abc # a package namespace math.sin # a module namespace OrderedDict.fromkeys # a class namespace mystring.upper # an instance namespace I call it a "clue" rather than definitive proof because the syntax is not quite the same for all namespaces. Local and global variables also exist in namespaces, but you don't use dotted notation for them. Another clue is that most of these are implemented by using a __dict__ to store the name:value mapping. Again, that's not universal: instances can optionally use __slots__ instead of __dict__ and packages use the file system. Apart from packages, one can use getattr(), setattr() and delattr() on all of these objects (modules, classes and instances) to manipulate their attributes. Wikipedia says: "In general, a namespace is a container for a set of identifiers (also known as symbols, names)." https://en.wikipedia.org/wiki/Namespace and that applies to packages, modules, classes, and instances. Last but not least, another clue: in some languages, such as Java, what Python calls "attributes" are known as *variables*. So per-instance members are called "instance variables", per-class members are sometimes called "class variables" (although not in Java, where I believe they are known as static variables for technical reasons). Personally, I don't like that terminology, but I do recognise that it does reflect a certain connection between names in local/global/instance/class namespaces. > BTW, the recommended Python 3.x way is > > class Rec (object): > pass I think you mean Python 2 rather than 3. In Python 2, we have legacy "old style" or "classic" classes, and "new style" classes which inherit from object. In Python 3, classic classes are gone, and inheriting from object is optional. > (whereas “pass” is a placeholder statement, a bit like the yada-yada > operator of Python) and you should start class identifiers uppercase > (therefore, “Rec” instead) in order to avoid name collisions with built-in > class identifiers (“str”, “int” etc.) and make it easier to tell apart > instantiations from function/method calls. Agreed! It is good practice to name classes with initial capital letter, and instances in all lowercase. > If you call that method as the method of a class (object), you need to > pass an argument for the first parameter because you have made it > positional, not > optional (it has no default value). If you pass (a reference to) the > class as first argument of that method, the class is the object whose > attribute is > accessed. Classes are objects (this, too, was probably derived from > Java). (In fact, AFAIK almost everything is an object in Python; there are > no primitive data types at all.) You are correct that "everything is an object" in Python, but wrong that this is derived from Java. As I understand it, Java classes are not values: you cannot assign a class to a variable, or create classes on the fly, or delete them, or stick them in lists, etc. Well, I say that you can't do it, but you actually can, using reflection and other tricks. But the important thing is that you need to use special techniques to work around the fact that classes aren't values and therefore not implemented as objects in Java. What is natural in Python is unnatural in Java. http://stackoverflow.com/questions/2320404/creating-classes-dynamically-with-java [...] > If you intend the function to be called as the method of an instance, you > would be well-advised to name the parameter “self”, as recommended. > (Which is probably derived from Smalltalk-80 and Self, some of the first > OOPLs.) Good advice. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | "Ivan Evstegneev" <webmailgroups@gmail.com> |
|---|---|
| Date | 2014-12-15 21:13 +0200 |
| Message-ID | <mailman.16986.1418670889.18130.python-list@python.org> |
| In reply to | #82540 |
Again Thanks for your help. I saw that there was a debate about "namespace" nature. That is what a book says about it(Learning Python 5 Ed. By Mark Lutz): ********************************************* "Classes and Instances Although they are technically two separate object types in the Python model, the classes and instances we put in these trees are almost identical—each type’s main purpose is to serve as another kind of namespace—a package of variables, and a place where we can attach attributes. If classes and instances therefore sound like modules, they should; however, the objects in class trees also have automatically searched links to other namespace objects, and classes correspond to statements, not entire files." "Customization via inheritance ....More generally, classes can build up namespace hierarchies, which define names to be used by objects created from classes in the hierarchy. This supports multiple customizable behaviors more directly than other tools." "...classes live in modules and are namespaces as well, but they add an extra component to attribute lookup called inheritance search." "In fact, classes have just three primary distinctions. At a base level, they are mostly just namespaces, much like the modules we studied in Part V. Unlike modules, though, classes also have support for generating multiple objects, for namespace inheritance, and for operator overloading." **************************************************************************** I'm not pretending to be a "smartass" here, but as I can understand from the context: Classes are namespaces, but they also have an additional capabilities. BR, Ivan > -----Original Message----- > From: Python-list [mailto:python-list- > bounces+webmailgroups=gmail.com@python.org] On Behalf Of Steven > D'Aprano > Sent: Monday, December 15, 2014 04:01 > To: python-list@python.org > Subject: Re: Classes - converting external function to class's method. > > Thomas 'PointedEars' Lahn wrote: > > > Ivan Evstegneev wrote: > > > >> I have stuck a bit with this example(took this one from the book). > >> > >> Here are a description steps of what I've done till now: > >> > >> > >> Step 1 - creating an empty namespace: > >> > >>>>>class rec: pass > > > > IMHO that is not actually creating a namespace; it is just > > declaring/defining an empty class. > > And classes are namespaces. As are instances. > > One clue is the fact that we use exactly the same syntax for accessing names in a > namespace regardless of whether the namespace is a package, a module, a class > or an instance: > > import collections.abc # a package namespace math.sin # a module namespace > OrderedDict.fromkeys # a class namespace mystring.upper # an instance > namespace > > I call it a "clue" rather than definitive proof because the syntax is not quite the > same for all namespaces. Local and global variables also exist in namespaces, but > you don't use dotted notation for them. > > Another clue is that most of these are implemented by using a __dict__ to store > the name:value mapping. Again, that's not universal: instances can optionally > use __slots__ instead of __dict__ and packages use the file system. > > Apart from packages, one can use getattr(), setattr() and delattr() on all of these > objects (modules, classes and instances) to manipulate their attributes. > > Wikipedia says: > > "In general, a namespace is a container for a set of identifiers (also known as > symbols, names)." > > https://en.wikipedia.org/wiki/Namespace > > and that applies to packages, modules, classes, and instances. > > Last but not least, another clue: in some languages, such as Java, what Python > calls "attributes" are known as *variables*. So per-instance members are called > "instance variables", per-class members are sometimes called "class variables" > (although not in Java, where I believe they are known as static variables for > technical reasons). Personally, I don't like that terminology, but I do recognise > that it does reflect a certain connection between names in > local/global/instance/class namespaces. > > > > BTW, the recommended Python 3.x way is > > > > class Rec (object): > > pass > > > I think you mean Python 2 rather than 3. In Python 2, we have legacy "old style" > or "classic" classes, and "new style" classes which inherit from object. In Python > 3, classic classes are gone, and inheriting from object is optional. > > > > (whereas “pass” is a placeholder statement, a bit like the yada-yada > > operator of Python) and you should start class identifiers uppercase > > (therefore, “Rec” instead) in order to avoid name collisions with > > built-in class identifiers (“str”, “int” etc.) and make it easier to > > tell apart instantiations from function/method calls. > > Agreed! > > It is good practice to name classes with initial capital letter, and instances in all > lowercase. > > > > If you call that method as the method of a class (object), you need to > > pass an argument for the first parameter because you have made it > > positional, not optional (it has no default value). If you pass (a > > reference to) the class as first argument of that method, the class is > > the object whose attribute is accessed. Classes are objects (this, > > too, was probably derived from Java). (In fact, AFAIK almost > > everything is an object in Python; there are no primitive data types > > at all.) > > You are correct that "everything is an object" in Python, but wrong that this is > derived from Java. As I understand it, Java classes are not values: > you cannot assign a class to a variable, or create classes on the fly, or delete > them, or stick them in lists, etc. > > Well, I say that you can't do it, but you actually can, using reflection and other > tricks. But the important thing is that you need to use special techniques to work > around the fact that classes aren't values and therefore not implemented as > objects in Java. What is natural in Python is unnatural in Java. > > http://stackoverflow.com/questions/2320404/creating-classes-dynamically- > with-java > > > [...] > > If you intend the function to be called as the method of an instance, > > you would be well-advised to name the parameter “self”, as recommended. > > (Which is probably derived from Smalltalk-80 and Self, some of the > > first > > OOPLs.) > > Good advice. > > > -- > Steven > > -- > https://mail.python.org/mailman/listinfo/python-list
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web