Therein I found extensive use of the keyword self, and coming from a primarily Java background, I find that I keep forgetting to type self. For example, instead of self.rect.centerx I would type rect.centerx, because, to me, rect is already a member variable of the class.
The Java parallel I can think of for this situation is having to prefix all references to member variables with this.
Am I stuck prefixing all member variables with self, or is there a way to declare them that would allow me to avoid having to do so?
Even if what I am suggesting isn’t pythonic, I’d still like to know if it is possible.
I have taken a look at these related SO questions, but they don’t quite answer what I am after:
class A(some_function()):def f(self):
self.member =42
self.method()
这就是完整的代码!(some_function返回用作基础的类型。)
另一个是动态组合类的方法的:
class B(object):passprint B()# <__main__.B object at 0xb7e4082c>def B_init(self):
self.answer =42def B_str(self):return"<The answer is %s.>"% self.answer
# notice these functions require no knowledge of the actual class# how hard are they to read and realize that "members" are used?
B.__init__ = B_init
B.__str__ = B_str
print B()# <The answer is 42.>
Python requires specifying self. The result is there’s never any confusion over what’s a member and what’s not, even without the full class definition visible. This leads to useful properties, such as: you can’t add members which accidentally shadow non-members and thereby break code.
One extreme example: you can write a class without any knowledge of what base classes it might have, and always know whether you are accessing a member or not:
class A(some_function()):
def f(self):
self.member = 42
self.method()
That’s the complete code! (some_function returns the type used as a base.)
Another, where the methods of a class are dynamically composed:
class B(object):
pass
print B()
# <__main__.B object at 0xb7e4082c>
def B_init(self):
self.answer = 42
def B_str(self):
return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?
B.__init__ = B_init
B.__str__ = B_str
print B()
# <The answer is 42.>
Remember, both of these examples are extreme and you won’t see them every day, nor am I suggesting you should often write code like this, but they do clearly show aspects of self being explicitly required.
import numpy as np
classMyFunkyGaussian():def __init__(self, A, x0, w, s, y0):
self.A = float(A)
self.x0 = x0
self.w = w
self.y0 = y0
self.s = s
# The correct way, but subjectively less readable to some (like me) def calc1(self, x):return(self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)* np.exp(-(x-self.x0)**2/self.w**2)*(1+self.s*(x-self.x0)**2)+ self.y0 )# The correct way if you really don't want to use 'self' in the calculationsdef calc2(self, x):# Explicity copy variables
A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return( A/( w*sqrt(pi))/(1+s*w**2/2)* exp(-(x-x0)**2/w**2)*(1+s*(x-x0)**2)+ y0 )# Probably a bad idea...def calc3(self, x):# Automatically copy every class vairablefor k in self.__dict__ :exec(k+'= self.'+k)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return( A/( w*sqrt(pi))/(1+s*w**2/2)* exp(-(x-x0)**2/w**2)*(1+s*(x-x0)**2)+ y0 )
g =MyFunkyGaussian(2.0,1.5,3.0,5.0,0.0)print(g.calc1(0.5))print(g.calc2(0.5))print(g.calc3(0.5))
第三个例子-即使用for k in self.__dict__ : exec(k+'= self.'+k)基本上就是问题的实质所在,但是让我清楚一点,我认为这通常不是一个好主意。
Previous answers are all basically variants of “you can’t” or “you shouldn’t”. While I agree with the latter sentiment, the question is technically still unanswered.
Furthermore, there are legitimate reasons why someone might want to do something along the lines of what the actual question is asking. One thing I run into sometimes is lengthy math equations where using long names makes the equation unrecognizable. Here are a couple ways of how you could do this in a canned example:
import numpy as np
class MyFunkyGaussian() :
def __init__(self, A, x0, w, s, y0) :
self.A = float(A)
self.x0 = x0
self.w = w
self.y0 = y0
self.s = s
# The correct way, but subjectively less readable to some (like me)
def calc1(self, x) :
return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
* np.exp( -(x-self.x0)**2/self.w**2)
* (1+self.s*(x-self.x0)**2) + self.y0 )
# The correct way if you really don't want to use 'self' in the calculations
def calc2(self, x) :
# Explicity copy variables
A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
# Probably a bad idea...
def calc3(self, x) :
# Automatically copy every class vairable
for k in self.__dict__ : exec(k+'= self.'+k)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))
The third example – i.e. using for k in self.__dict__ : exec(k+'= self.'+k) is basically what the question is actually asking for, but let me be clear that I don’t think it is generally a good idea.
For more info, and ways to iterate through class variables, or even functions, see answers and discussion to this question. For a discussion of other ways to dynamically name variables, and why this is usually not a good idea see this blog post.
UPDATE: There appears to be no way to dynamically update or change locals in a function in Python3, so calc3 and similar variants are no longer possible. The only python3 compatible solution I can think of now is to use globals:
def calc4(self, x) :
# Automatically copy every class variable in globals
globals().update(self.__dict__)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
Which, again, would be a terrible practice in general.
Actually self is not a keyword, it’s just the name conventionally given to the first parameter of instance methods in Python. And that first parameter can’t be skipped, as it’s the only mechanism a method has of knowing which instance of your class it’s being called on.
回答 3
您可以使用任何想要的名称,例如
class test(object):def function(this, variable):
this.variable = variable
甚至
class test(object):def function(s, variable):
s.variable = variable
yes, you must always specify self, because explicit is better than implicit, according to python philosophy.
You will also find out that the way you program in python is very different from the way you program in java, hence the use of self tends to decrease because you don’t project everything inside the object. Rather, you make larger use of module-level function, which can be better tested.
by the way. I hated it at first, now I hate the opposite. same for indented-driven flow control.
The “self” is the conventional placeholder of the current object instance of a class. Its used when you want to refer to the object’s property or field or method inside a class as if you’re referring to “itself”. But to make it shorter someone in the Python programming realm started to use “self” , other realms use “this” but they make it as a keyword which cannot be replaced. I rather used “its” to increase the code readability. Its one of the good things in Python – you have a freedom to choose your own placeholder for the object’s instance other than “self”.
Example for self:
Actually you can use recipe “Implicit self” from Armin Ronacher presentation “5 years of bad ideas” ( google it).
It’s a very clever recipe, as almost everything from Armin Ronacher, but I don’t think this idea is very appealing. I think I’d prefer explicit this in C#/Java.
…a hybrid approach works best. All of your class methods that actually
do computation should be moved into closures, and extensions to clean up syntax should be kept in classes. Stuff the closures into classes, treating the class much like a namespace. The closures are essentially static functions, and so do not require selfs*, even in the class…
I think that it would be easier and more readable if there was a statement “member” just as there is “global” so you can tell the interpreter which are the objects members of the class.
What you’re wanting to do isn’t possible. Take, for instance, whether or not the code below looks valid:
class Test(object):
def _decorator(self, foo):
foo()
def bar(self):
pass
bar = self._decorator(bar)
It, of course, isn’t valid since self isn’t defined at that point. The same goes for Test as it won’t be defined until the class itself is defined (which its in the process of). I’m showing you this code snippet because this is what your decorator snippet transforms into.
So, as you can see, accessing the instance in a decorator like that isn’t really possible since decorators are applied during the definition of whatever function/method they are attached to and not during instantiation.
class myclass(object):def __init__(self):
self.property ="HELLO"@adecorator(property="GOODBYE")def method(self):print self.property
这是装饰代码
class adecorator (object):def __init__ (self,*args,**kwargs):# store arguments passed to the decorator
self.args = args
self.kwargs = kwargs
def __call__(self, func):def newf(*args,**kwargs):#the 'self' for a method function is passed as args[0]
slf = args[0]# replace and store the attributes
saved ={}for k,v in self.kwargs.items():if hasattr(slf, k):
saved[k]= getattr(slf,k)
setattr(slf, k, v)# call the method
ret = func(*args,**kwargs)#put things backfor k,v in saved.items():
setattr(slf, k, v)return ret
newf.__doc__ = func.__doc__
return newf
I use this type of decorator in some debugging situations, it allows overriding class properties by decorating, without having to find the calling function.
class adecorator (object):
def __init__ (self, *args, **kwargs):
# store arguments passed to the decorator
self.args = args
self.kwargs = kwargs
def __call__(self, func):
def newf(*args, **kwargs):
#the 'self' for a method function is passed as args[0]
slf = args[0]
# replace and store the attributes
saved = {}
for k,v in self.kwargs.items():
if hasattr(slf, k):
saved[k] = getattr(slf,k)
setattr(slf, k, v)
# call the method
ret = func(*args, **kwargs)
#put things back
for k,v in saved.items():
setattr(slf, k, v)
return ret
newf.__doc__ = func.__doc__
return newf
Note: because I’ve used a class decorator you’ll need to use @adecorator() with the brackets on to decorate functions, even if you don’t pass any arguments to the decorator class constructor.
classOutputAnalysis(object):"analyze the output of diagnostic commands"def handler_for(name):"decorator to associate a function with a command"def wrapper(func):
func.handler_for = name
return func
return wrapper
# associate mount_p with 'mount_-p.txt'@handler_for('mount -p')def mount_p(self, slurped):pass
现在,我们已将某些数据与每个类方法相关联,我们需要收集该数据并将其存储在class属性中。
OutputAnalysis.cmd_handler ={}for value inOutputAnalysis.__dict__.itervalues():try:OutputAnalysis.cmd_handler[value.handler_for]= value
exceptAttributeError:pass
I found this question while researching a very similar problem. My solution is to split the problem into two parts. First, you need to capture the data that you want to associate with the class methods. In this case, handler_for will associate a Unix command with handler for that command’s output.
class OutputAnalysis(object):
"analyze the output of diagnostic commands"
def handler_for(name):
"decorator to associate a function with a command"
def wrapper(func):
func.handler_for = name
return func
return wrapper
# associate mount_p with 'mount_-p.txt'
@handler_for('mount -p')
def mount_p(self, slurped):
pass
Now that we’ve associated some data with each class method, we need to gather that data and store it in a class attribute.
OutputAnalysis.cmd_handler = {}
for value in OutputAnalysis.__dict__.itervalues():
try:
OutputAnalysis.cmd_handler[value.handler_for] = value
except AttributeError:
pass
回答 6
这是迈克尔·斯佩尔(Michael Speer)的答案的扩展,以进一步采取一些措施:
一个实例方法装饰器,它接受参数并通过参数和返回值作用于函数。
classTest(object):"Prints if x == y. Throws an error otherwise."def __init__(self, x):
self.x = x
def _outer_decorator(y):def _decorator(foo):def magic(self,*args,**kwargs):print("start magic")if self.x == y:return foo(self,*args,**kwargs)else:raiseValueError("x ({}) != y ({})".format(self.x, y))print("end magic")return magic
return _decorator
@_outer_decorator(y=3)def bar(self,*args,**kwargs):print("normal call")print("args: {}".format(args))print("kwargs: {}".format(kwargs))return27
然后
In[2]:
test =Test(3)
test.bar(13,'Test',
q=9,
lollipop=[1,2,3])
start magic
normal call
args:(13,'Test')
kwargs:{'q':9,'lollipop':[1,2,3]}Out[2]:27In[3]:
test =Test(4)
test.bar(13,'Test',
q=9,
lollipop=[1,2,3])
start magic
---------------------------------------------------------------------------ValueErrorTraceback(most recent call last)<ipython-input-3-576146b3d37e>in<module>()4'Test',5 q=9,---->6 lollipop=[1,2,3]7)<ipython-input-1-428f22ac6c9b>in magic(self,*args,**kwargs)11return foo(self,*args,**kwargs)12else:--->13raiseValueError("x ({}) != y ({})".format(self.x, y))14print("end magic")15return magic
ValueError: x (4)!= y (3)
Decorators seem better suited to modify the functionality of an entire object (including function objects) versus the functionality of an object method which in general will depend on instance attributes. For example:
When defining a method on a class in Python, it looks something like this:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
But in some other languages, such as C#, you have a reference to the object that the method is bound to with the “this” keyword without declaring it as an argument in the method prototype.
Was this an intentional language design decision in Python or are there some implementation details that require the passing of “self” as an argument?
I like to quote Peters’ Zen of Python. “Explicit is better than implicit.”
In Java and C++, ‘this.‘ can be deduced, except when you have variable names that make it impossible to deduce. So you sometimes need it and sometimes don’t.
Python elects to make things like this explicit rather than based on a rule.
Additionally, since nothing is implied or assumed, parts of the implementation are exposed. self.__class__, self.__dict__ and other “internal” structures are available in an obvious way.
It’s to minimize the difference between methods and functions. It allows you to easily generate methods in metaclasses, or add methods at runtime to pre-existing classes.
When a method definition is decorated, we don’t know whether to automatically give it a ‘self’ parameter or not: the decorator could turn the function into a static method (which has no ‘self’), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it’s trivial to write a decorator that implements ‘@classmethod’ or ‘@staticmethod’ in pure Python). There’s no way without knowing what the decorator does whether to endow the method being defined with an implicit ‘self’ argument or not.
I reject hacks like special-casing ‘@classmethod’ and ‘@staticmethod’.
Python doesn’t force you on using “self”. You can give it whatever name you want. You just have to remember that the first argument in a method definition header is a reference to the object.
from functools import partial
classMagicMethod(object):"""Does black magic when called"""def __get__(self, obj, obj_type):# This binds the <other> class instance to the <innocent_self> parameter# of the method MagicMethod.invokereturn partial(self.invoke, obj)def invoke(magic_self, innocent_self,*args,**kwargs):# do black magic here...print magic_self, innocent_self, args, kwargs
classInnocentClass(object):
magic_method =MagicMethod()
Also allows you to do this: (in short, invoking Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5) will return 12, but will do so in the craziest of ways.
class Outer(object):
def __init__(self, outer_num):
self.outer_num = outer_num
def create_inner_class(outer_self, inner_arg):
class Inner(object):
inner_arg = inner_arg
def weird_sum_with_closure_scope(inner_self, num)
return num + outer_self.outer_num + inner_arg
return Inner
Of course, this is harder to imagine in languages like Java and C#. By making the self reference explicit, you’re free to refer to any object by that self reference. Also, such a way of playing with classes at runtime is harder to do in the more static languages – not that’s it’s necessarily good or bad. It’s just that the explicit self allows all this craziness to exist.
Moreover, imagine this: We’d like to customize the behavior of methods (for profiling, or some crazy black magic). This can lead us to think: what if we had a class Method whose behavior we could override or control?
Well here it is:
from functools import partial
class MagicMethod(object):
"""Does black magic when called"""
def __get__(self, obj, obj_type):
# This binds the <other> class instance to the <innocent_self> parameter
# of the method MagicMethod.invoke
return partial(self.invoke, obj)
def invoke(magic_self, innocent_self, *args, **kwargs):
# do black magic here
...
print magic_self, innocent_self, args, kwargs
class InnocentClass(object):
magic_method = MagicMethod()
And now: InnocentClass().magic_method() will act like expected. The method will be bound with the innocent_self parameter to InnocentClass, and with the magic_self to the MagicMethod instance. Weird huh? It’s like having 2 keywords this1 and this2 in languages like Java and C#. Magic like this allows frameworks to do stuff that would otherwise be much more verbose.
Again, I don’t want to comment on the ethics of this stuff. I just wanted to show things that would be harder to do without an explicit self reference.
I think the real reason besides “The Zen of Python” is that Functions are first class citizens in Python.
Which essentially makes them an Object. Now The fundamental issue is if your functions are object as well then, in Object oriented paradigm how would you send messages to Objects when the messages themselves are objects ?
Looks like a chicken egg problem, to reduce this paradox, the only possible way is to either pass a context of execution to methods or detect it. But since python can have nested functions it would be impossible to do so as the context of execution would change for inner functions.
This means the only possible solution is to explicitly pass ‘self’ (The context of execution).
So i believe it is a implementation problem the Zen came much later.
Names in class scope are not accessible. Names are resolved in the
innermost enclosing function scope. If a class definition occurs in a
chain of nested scopes, the resolution process skips class
definitions. This rule prevents odd interactions between class
attributes and local variable access. If a name binding operation
occurs in a class definition, it creates an attribute on the resulting
class object. To access this variable in a method, or in a function
nested within a method, an attribute reference must be used, either
via self or via the class name.
anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit). This is the reason the first parameter of a function in class must be the object itself.
class Point(object):
def __init__(self,x = 0,y = 0):
self.x = x
self.y = y
def distance(self):
"""Find distance from origin"""
return (self.x**2 + self.y**2) ** 0.5
Invocations:
>>> p1 = Point(6,8)
>>> p1.distance()
10.0
init() defines three parameters but we just passed two (6 and 8). Similarly distance() requires one but zero arguments were passed.
Why is Python not complaining about this argument number mismatch?
Generally, when we call a method with some arguments, the corresponding class function is called by placing the method’s object before the first argument. So, anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit).
This is the reason the first parameter of a function in class must be the object itself. Writing this parameter as self is merely a convention. It is not a keyword and has no special meaning in Python. We could use other names (like this) but I strongly suggest you not to. Using names other than self is frowned upon by most developers and degrades the readability of the code (“Readability counts”).
…
In, the first example self.x is an instance attribute whereas x is a local variable. They are not the same and lie in different namespaces.
Self Is Here To Stay
Many have proposed to make self a keyword in Python, like this in C++ and Java. This would eliminate the redundant use of explicit self from the formal parameter list in methods. While this idea seems promising, it’s not going to happen. At least not in the near future. The main reason is backward compatibility. Here is a blog from the creator of Python himself explaining why the explicit self has to stay.
cls implies that method belongs to the class while self implies that the method is related to instance of the class,therefore member with cls is accessed by class name where as the one with self is accessed by instance of the class…it is the same concept as static member and non-static members in java if you are from java background.
def moon(self, moon_name):
self.MName= moon_name
#but here cls method its use is different @classmethoddef moon(cls, moon_name):
instance = cls()
instance.MName= moon_name
This is very good question but not as wanting as question.
There is difference between ‘self’ and ‘cls’ used method though analogically they are at same place
def moon(self, moon_name):
self.MName = moon_name
#but here cls method its use is different
@classmethod
def moon(cls, moon_name):
instance = cls()
instance.MName = moon_name
Now you can see both are moon function but one can be used inside class while other function name moon can be used for any class.
For practical programming approach :
While designing circle class we use area method as cls instead of self because we don’t want area to be limited to particular class of circle only .
Instead of accepting a self parameter, class methods take a cls parameter that points to the class—and not the object instance—when
the method is called.
Since the class method only has access to this cls argument, it can’t
modify object instance state. That would require access to self . However, class methods can still modify class state that applies across all
instances of the class.
…is syntactic sugar, which the interpreter translates behind the scenes into:
MyClass.method(my_object, "foo")
…which, as you can see, does indeed have two arguments – it’s just that the first one is implicit, from the point of view of the caller.
This is because most methods do some work with the object they’re called on, so there needs to be some way for that object to be referred to inside the method. By convention, this first argument is called self inside the method definition:
class MyNewClass:
def method(self, arg):
print(self)
print(arg)
If you call method("foo") on an instance of MyNewClass, it works as expected:
Occasionally (but not often), you really don’t care about the object that your method is bound to, and in that circumstance, you can decorate the method with the builtin staticmethod() function to say so:
class MyOtherClass:
@staticmethod
def method(arg):
print(arg)
…in which case you don’t need to add a self argument to the method definition, and it still works:
Something else to consider when this type of error is encountered:
I was running into this error message and found this post helpful. Turns out in my case I had overridden an __init__() where there was object inheritance.
The inherited example is rather long, so I’ll skip to a more simple example that doesn’t use inheritance:
class MyBadInitClass:
def ___init__(self, name):
self.name = name
def name_foo(self, arg):
print(self)
print(arg)
print("My name is", self.name)
class MyNewClass:
def new_foo(self, arg):
print(self)
print(arg)
my_new_object = MyNewClass()
my_new_object.new_foo("NewFoo")
my_bad_init_object = MyBadInitClass(name="Test Name")
my_bad_init_object.name_foo("name foo")
Result is:
<__main__.MyNewClass object at 0x033C48D0>
NewFoo
Traceback (most recent call last):
File "C:/Users/Orange/PycharmProjects/Chapter9/bad_init_example.py", line 41, in <module>
my_bad_init_object = MyBadInitClass(name="Test Name")
TypeError: object() takes no parameters
PyCharm didn’t catch this typo. Nor did Notepad++ (other editors/IDE’s might).
Granted, this is a “takes no parameters” TypeError, it isn’t much different than “got two” when expecting one, in terms of object initialization in Python.
Addressing the topic: An overloading initializer will be used if syntactically correct, but if not it will be ignored and the built-in used instead. The object won’t expect/handle this and the error is thrown.
In the case of the sytax error: The fix is simple, just edit the custom init statement:
… the self variable represents the instance of the object itself. Most object-oriented languages pass this as a hidden parameter to the methods defined on an object; Python does not. You have to declare it explicitly. When you create an instance of the A class and call its methods, it will be passed automatically, as in …
a = A() # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument
The __init__ method is roughly what represents a constructor in Python. When you call A() Python creates an object for you, and passes it as the first parameter to the __init__ method. Any additional parameters (e.g., A(24, 'Hello')) will also get passed as arguments–in this case causing an exception to be raised, since the constructor isn’t expecting them.
回答 1
是的,您是对的,这些是oop结构。
__init__是一个类的构造函数。该self参数是指对象的实例(如this在C ++中)。
classPoint:def __init__(self, x, y):
self._x = x
self._y = y
__init__ is the constructor for a class. The self parameter refers to the instance of the object (like this in C++).
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
The __init__ method gets called when memory for the object is allocated:
x = Point(1,2)
It is important to use the self parameter inside an object’s method if you want to persist the value with the object. If, for instance, you implement the __init__ method like this:
class Point:
def __init__(self, x, y):
_x = x
_y = y
Your x and y parameters would be stored in variables on the stack and would be discarded when the init method goes out of scope. Setting those variables as self._x and self._y sets those variables as members of the Point object (accessible for the lifetime of the object).
In the hope it might help a little, here’s a simple example I used to understand the difference between a variable declared inside a class, and a variable declared inside an __init__ function:
class MyClass(object):
i = 123
def __init__(self):
self.i = 345
a = MyClass()
print(a.i)
print(MyClass.i)
self as it suggests, refers to itself– the object which has called the method. That is, if you have N objects calling the method, then self.a will refer to a separate instance of the variable for each of the N objects. Imagine N copies of the variable a for each object
__init__ is what is called as a constructor in other OOP languages such as C++/Java. The basic idea is that it is a special method which is automatically called when an object of that Class is created
__init__ does act like a constructor. You’ll need to pass “self” to any class functions as the first argument if you want them to behave as non-static methods. “self” are instance variables for your class.
classBill():def __init__(self,apples,figs,dates):
self.apples = apples
self.figs = figs
self.dates = dates
self.bill = apples + figs + datesprint("Buy",self.apples,"apples", self.figs,"figs
and",self.dates,"dates.
Total fruitty bill is",self.bill," pieces of fruit :)")
创建Bill类的实例时:
purchase =Bill(5,6,7)
你得到:
>Buy5 apples 6 figs and7 dates.Total fruitty bill is18 pieces of> fruit :)
Class objects support two kinds of operations: attribute references and instantiation
Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created. So, if the class definition looked like this:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of MyClass.i by assignment. __doc__ is also a valid attribute, returning the docstring belonging to the class: “A simple example class”.
Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example:
x = MyClass()
The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:
def __init__(self):
self.data = []
When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance. So in this example, a new, initialized instance can be obtained by:
x = MyClass()
Of course, the __init__() method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__(). For example,
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
x.r, x.i
Taken from official documentation which helped me the most in the end.
Here is my example
class Bill():
def __init__(self,apples,figs,dates):
self.apples = apples
self.figs = figs
self.dates = dates
self.bill = apples + figs + dates
print ("Buy",self.apples,"apples", self.figs,"figs
and",self.dates,"dates.
Total fruitty bill is",self.bill," pieces of fruit :)")
When you create instance of class Bill:
purchase = Bill(5,6,7)
You get:
> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18 pieces of
> fruit :)
Had trouble undestanding this myself. Even after reading the answers here.
To properly understand the __init__ method you need to understand self.
The self Parameter
The arguments accepted by the __init__ method are :
def __init__(self, arg1, arg2):
But we only actually pass it two arguments :
instance = OurClass('arg1', 'arg2')
Where has the extra argument come from ?
When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.
In order to access object attributes from within the __init__ method we need a reference to the object.
Whenever a method is called, a reference to the main object is passed as the first argument. By convention you always call this first argument to your methods self.
This means in the __init__ method we can do :
self.arg1 = arg1
self.arg2 = arg2
Here we are setting attributes on the object. You can verify this by doing the following :
Basically, you need to use the ‘self’ keyword when using a variable in multiple functions within the same class. As for init, it’s used to setup default values incase no other functions from within that class are called.
__init__ is basically a function which will “initialize”/“activate” the properties of the class for a specific object, once created and matched to the corresponding class..
self represents that object which will inherit those properties.
Now we can create an instance of foo and call the method on it, the self parameter is added by Python in this case:
f = foo()
f.bar()
But it can be passed in as well if the method call isn’t in the context of an instance of the class, the code below does the same thing
f = foo()
foo.bar(f)
Interestingly the variable name ‘self’ is just a convention. The below definition will work exactly the same.. Having said that it is very strong convention which should be followed always, but it does say something about flexible nature of the language
class foo:
def bar(s):
print "hi"
回答 12
只是演示的问题。
classMyClass:def __init__(self):print('__init__ is the constructor for a class')def __del__(self):print('__del__ is the destructor for a class')def __enter__(self):print('__enter__ is for context manager')return self
def __exit__(self, exc_type, exc_value, traceback):print('__exit__ is for context manager')def greeting(self):print('hello python')if __name__ =='__main__':withMyClass()as mycls:
mycls.greeting()
$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ isfor context manager
hello python
__exit__ isfor context manager
__del__ is the destructor for a class
class MyClass:
def __init__(self):
print('__init__ is the constructor for a class')
def __del__(self):
print('__del__ is the destructor for a class')
def __enter__(self):
print('__enter__ is for context manager')
return self
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__ is for context manager')
def greeting(self):
print('hello python')
if __name__ == '__main__':
with MyClass() as mycls:
mycls.greeting()
$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
回答 13
在此代码中:
classCat:def __init__(self, name):
self.name = name
def info(self):print'I am a cat and I am called', self.name
class Cat:
def __init__(self, name):
self.name = name
def info(self):
print 'I am a cat and I am called', self.name
Here __init__ acts as a constructor for the class and when an object is instantiated, this function is called. self represents the instantiating object.
c = Cat('Kitty')
c.info()
The result of the above statements will be as follows:
What does self do? What is it meant to be? Is it mandatory?
The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.
Python doesn’t force you on using “self“. You can give it any name you want. But remember the first argument in a method definition is a reference to the object. Python adds the self argument to the list for you; you do not need to include it when you call the methods.
if you didn’t provide self in init method then you will get an error
TypeError: __init___() takes no arguments (1 given)
What does the init method do? Why is it necessary? (etc.)
init is short for initialization. It is a constructor which gets called when you make an instance of the class and it is not necessary. But usually it our practice to write init method for setting default state of the object. If you are not willing to set any state of the object initially then you don’t need to write this method.
回答 15
# Source: Class and Instance Variables# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variablesclassMyClass(object):# class variable
my_CLS_var =10# sets "init'ial" state to objects/instances, use self argumentdef __init__(self):# self usage => instance variable (per object)
self.my_OBJ_var =15# also possible, class name is used => init class variableMyClass.my_CLS_var =20def run_example_func():# PRINTS 10 (class variable)printMyClass.my_CLS_var
# executes __init__ for obj1 instance# NOTE: __init__ changes class variable above
obj1 =MyClass()# PRINTS 15 (instance variable)print obj1.my_OBJ_var
# PRINTS 20 (class variable, changed value)printMyClass.my_CLS_var
run_example_func()
When we create an instance of the object, the __init__ is called to customize the object after it has been created. That is, when we call SomeObject with 'blah' below (which could be anything), it gets passed to the __init__ function as the argument, blah:
an_object = SomeObject('blah')
The self argument is the instance of SomeObject that will be assigned to an_object.
Later, we might want to call a method on this object:
an_object.method()
Doing the dotted lookup, that is, an_object.method, binds the instance to an instance of the function, and the method (as called above) is now a “bound” method – which means we do not need to explicitly pass the instance to the method call.
The method call gets the instance because it was bound on the dotted lookup, and when called, then executes whatever code it was programmed to perform.
The implicitly passed self argument is called self by convention. We could use any other legal Python name, but you will likely get tarred and feathered by other Python programmers if you change it to something else.
__init__ is a special method, documented in the Python datamodel documentation. It is called immediately after the instance is created (usually via __new__ – although __new__ is not required unless you are subclassing an immutable datatype).
self? So what’s with that self parameter to all of the Customer
methods? What is it? Why, it’s the instance, of course! Put another
way, a method like withdraw defines the instructions for withdrawing
money from some abstract customer’s account. Calling
jeff.withdraw(100.0) puts those instructions to use on the jeff
instance.
So when we say def withdraw(self, amount):, we’re saying, “here’s how
you withdraw money from a Customer object (which we’ll call self) and
a dollar figure (which we’ll call amount). self is the instance of the
Customer that withdraw is being called on. That’s not me making
analogies, either. jeff.withdraw(100.0) is just shorthand for
Customer.withdraw(jeff, 100.0), which is perfectly valid (if not often
seen) code.
init self may make sense for other methods, but what about init? When we call init, we’re in the process of creating an object, so how can there already be a self? Python allows us to extend
the self pattern to when objects are constructed as well, even though
it doesn’t exactly fit. Just imagine that jeff = Customer(‘Jeff
Knupp’, 1000.0) is the same as calling jeff = Customer(jeff, ‘Jeff
Knupp’, 1000.0); the jeff that’s passed in is also made the result.
This is why when we call init, we initialize objects by saying
things like self.name = name. Remember, since self is the instance,
this is equivalent to saying jeff.name = name, which is the same as
jeff.name = ‘Jeff Knupp. Similarly, self.balance = balance is the same
as jeff.balance = 1000.0. After these two lines, we consider the
Customer object “initialized” and ready for use.
Be careful what you __init__
After init has finished, the caller can rightly assume that the
object is ready to use. That is, after jeff = Customer(‘Jeff Knupp’,
1000.0), we can start making deposit and withdraw calls on jeff; jeff is a fully-initialized object.
What is the purpose of the self word in Python? I understand it refers to the specific object created from that class, but I can’t see why it explicitly needs to be added to every function as a parameter. To illustrate, in Ruby I can do this:
class myClass
def myFunc(name)
@name = name
end
end
Which I understand, quite easily. However in Python I need to include self:
class myClass:
def myFunc(self, name):
self.name = name
Can anyone talk me through this? It is not something I’ve come across in my (admittedly limited) experience.
The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it’s just another object.
Python could have done something else to distinguish normal names from attributes — special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different — but it didn’t. Python’s all for making things explicit, making it obvious what’s what, and although it doesn’t do it entirely everywhere, it does do it for instance attributes. That’s why assigning to an instance attribute needs to know what instance to assign to, and that’s why it needs self..
回答 1
让我们看一个简单的向量类:
classVector:def __init__(self, x, y):
self.x = x
self.y = y
So the whole structure stays the same. How can me make use of this? If we assume for a moment that we hadn’t written a length method for our Vector class, we could do this:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
This works because the first parameter of length_global, can be re-used as the self parameter in length_new. This would not be possible without an explicit self.
Another way of understanding the need for the explicit self is to see where Python adds some syntactical sugar. When you keep in mind, that basically, a call like
v_instance.length()
is internally transformed to
Vector.length(v_instance)
it is easy to see where the self fits in. You don’t actually write instance methods in Python; what you write is class methods which must take an instance as a first parameter. And therefore, you’ll have to place the instance parameter somewhere explicitly.
When objects are instantiated, the object itself is passed into the self parameter.
Because of this, the object’s data is bound to the object. Below is an example of how you might like to visualize what each object’s data might look. Notice how ‘self’ is replaced with the objects name. I’m not saying this example diagram below is wholly accurate but it hopefully with serve a purpose in visualizing the use of self.
The Object is passed into the self parameter so that the object can keep hold of its own data.
Although this may not be wholly accurate, think of the process of instantiating an object like this: When an object is made it uses the class as a template for its own data and methods. Without passing it’s own name into the self parameter, the attributes and methods in the class would remain as a general template and would not be referenced to (belong to) the object. So by passing the object’s name into the self parameter it means that if 100 objects are instantiated from the one class, they can all keep track of their own data and methods.
See the illustration below:
回答 4
我喜欢这个例子:
class A:
foo =[]
a, b = A(), A()
a.foo.append(5)
b.foo
ans:[5]class A:def __init__(self):
self.foo =[]
a, b = A(), A()
a.foo.append(5)
b.foo
ans:[]
class A:
foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]
class A:
def __init__(self):
self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
Classes are just a way to avoid passing in this “state” thing all the time (and other nice things like initializing, class composition, the rarely-needed metaclasses, and supporting custom methods to override operators).
Now let’s demonstrate the above code using the built-in python class machinery, to show how it’s basically the same thing.
class State(object):
def __init__(self):
self.field = 'init'
def add(self, x):
self.field += x
def mult(self, x):
self.field *= x
s = State()
s.add('added') # self is implicitly passed in
s.mult(2) # self is implicitly passed in
print( s.field )
[migrated my answer from duplicate closed question]
As in Modula-3, there are no shorthands [in Python] for referencing the object’s members from its methods: the method function is declared with an explicit first argument representing the object, which is provided implicitly by the call.
Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers, and it is also conceivable that a class browser program might be written that relies upon such a convention.
class C1(object):def __init__(self):print"C1 init"class C2(C1):def __init__(self):#overrides C1.__init__print"C2 init"
C1.__init__(self)#but we still want C1 to init the class too
As well as all the other reasons already stated, it allows for easier access to overridden methods; you can call Class.some_method(inst).
An example of where it’s useful:
class C1(object):
def __init__(self):
print "C1 init"
class C2(C1):
def __init__(self): #overrides C1.__init__
print "C2 init"
C1.__init__(self) #but we still want C1 to init the class too
Python is not a language built for Object Oriented Programming unlike Java or C++.
When calling a static method in Python, one simply writes a method with regular arguments inside it.
class Animal():
def staticMethod():
print "This is a static method"
However, an object method, which requires you to make a variable, which is an Animal, in this case, needs the self argument
class Animal():
def objectMethod(self):
print "This is an object method which needs an instance of a class"
The self method is also used to refer to a variable field within the class.
class Animal():
#animalName made in constructor
def Animal(self):
self.animalName = "";
def getAnimalName(self):
return self.animalName
In this case, self is referring to the animalName variable of the entire class. REMEMBER: If you have a variable within a method, self will not work. That variable is simply existent only while that method is running. For defining fields (the variables of the entire class), you have to define them OUTSIDE the class methods.
If you don’t understand a single word of what I am saying, then Google “Object Oriented Programming.” Once you understand this, you won’t even need to ask that question :).
It’s there to follow the Python zen “explicit is better than implicit”. It’s indeed a reference to your class object. In Java and PHP, for example, it’s called this.
If user_type_name is a field on your model you access it by self.user_type_name.
classStudent:#called each time you create a new Student instancedef __init__(self,name,age):#special method to initialize
self.name=name
self.age=age
def __str__(self):#special method called for example when you use printreturn"Student %s is %s years old"%(self.name,self.age)def call(self, msg):#silly example for custom methodreturn("Hey, %s! "+msg)%self.name
#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)#using themprint bob.name
print bob.age
print alice #this one only works if you define the __str__ methodprint alice.call("Come here!")#notice you don't put a value for self#you can modify attributes, like when alice ages
alice.age=20print alice
First of all, self is a conventional name, you could put anything else (being coherent) in its stead.
It refers to the object itself, so when you are using it, you are declaring that .name and .age are properties of the Student objects (note, not of the Student class) you are going to create.
class Student:
#called each time you create a new Student instance
def __init__(self,name,age): #special method to initialize
self.name=name
self.age=age
def __str__(self): #special method called for example when you use print
return "Student %s is %s years old" %(self.name,self.age)
def call(self, msg): #silly example for custom method
return ("Hey, %s! "+msg) %self.name
#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)
#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self
#you can modify attributes, like when alice ages
alice.age=20
print alice
self is an object reference to the object itself, therefore, they are same.
Python methods are not called in the context of the object itself.
self in Python may be used to deal with custom object models or something.
classMyClass():def staticMethod():print"This is a static method"def objectMethod(self):print"This is an object method which needs an instance of a class, and that is what self refers to"
The use of the argument, conventionally called self isn’t as hard to understand, as is why is it necessary? Or as to why explicitly mention it? That, I suppose, is a bigger question for most users who look up this question, or if it is not, they will certainly have the same question as they move forward learning python. I recommend them to read these couple of blogs:
The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called. For example the below code is the same as the above code.
Another thing I would like to add is, an optional self argument allows me to declare static methods inside a class, by not writing self.
Code examples:
class MyClass():
def staticMethod():
print "This is a static method"
def objectMethod(self):
print "This is an object method which needs an instance of a class, and that is what self refers to"
PS:This works only in Python 3.x.
In previous versions, you have to explicitly add @staticmethod decorator, otherwise self argument is obligatory.
I’m surprised nobody has brought up Lua. Lua also uses the ‘self’ variable however it can be omitted but still used. C++ does the same with ‘this’. I don’t see any reason to have to declare ‘self’ in each function but you should still be able to use it just like you can with lua and C++. For a language that prides itself on being brief it’s odd that it requires you to declare the self variable.
回答 15
请看以下示例,该示例清楚地说明了 self
classRestaurant(object):
bankrupt =Falsedef open_branch(self):ifnot self.bankrupt:print("branch opened")#create instance1>>> x =Restaurant()>>> x.bankrupt
False#create instance2>>> y =Restaurant()>>> y.bankrupt =True>>> y.bankrupt
True>>> x.bankrupt
False
Is because by the way python is designed the alternatives would hardly work. Python is designed to allow methods or functions to be defined in a context where both implicit this (a-la Java/C++) or explicit @ (a-la ruby) wouldn’t work. Let’s have an example with the explicit approach with python conventions:
def fubar(x):
self.x = x
class C:
frob = fubar
Now the fubar function wouldn’t work since it would assume that self is a global variable (and in frob as well). The alternative would be to execute method’s with a replaced global scope (where self is the object).
The implicit approach would be
def fubar(x)
myX = x
class C:
frob = fubar
This would mean that myX would be interpreted as a local variable in fubar (and in frob as well). The alternative here would be to execute methods with a replaced local scope which is retained between calls, but that would remove the posibility of method local variables.
However the current situation works out well:
def fubar(self, x)
self.x = x
class C:
frob = fubar
here when called as a method frob will receive the object on which it’s called via the self parameter, and fubar can still be called with an object as parameter and work the same (it is the same as C.frob I think).
In the __init__ method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.
self, as a name, is just a convention, call it as you want ! but when using it, for example to delete the object, you have to use the same name: __del__(var), where var was used in the __init__(var,[...])
You should take a look at cls too, to have the bigger picture. This post could be helpful.
回答 18
self的作用类似于当前的对象名称或class的实例。
# Self explanation.class classname(object):def __init__(self,name):
self.name=name
# Self is acting as a replacement of object name.#self.name=object1.namedef display(self):print("Name of the person is :",self.name)print("object name:",object1.name)
object1=classname("Bucky")
object2=classname("ford")
object1.display()
object2.display()###### Output Name of the person is:Bucky
object name:BuckyName of the person is: ford
object name:Bucky
self is acting as like current object name or instance of class .
# Self explanation.
class classname(object):
def __init__(self,name):
self.name=name
# Self is acting as a replacement of object name.
#self.name=object1.name
def display(self):
print("Name of the person is :",self.name)
print("object name:",object1.name)
object1=classname("Bucky")
object2=classname("ford")
object1.display()
object2.display()
###### Output
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky
If we would just stick to functional programming we would not need self.
Once we enter the Python OOP we find self there.
Here is the typical use case class C with the method m1
class C:
def m1(self, arg):
print(self, ' inside')
pass
ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address
This program will output:
<__main__.C object at 0x000002B9D79C6CC0> outside
<__main__.C object at 0x000002B9D79C6CC0> inside
0x2b9d79c6cc0
So self holds the memory address of the class instance.
The purpose of self would be to hold the reference for instance methods and for us to have explicit access to that reference.
Note there are three different types of class methods:
the special thing about methods is that the instance object is passed as the first argument of the function. In our example, the call x.f() is exactly equivalent to MyClass.f(x). In general, calling a method with a list of n arguments is equivalent to calling the corresponding function with an argument list that is created by inserting the method’s instance object before the first argument.
preceding this the related snippet,
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'