三篇文章,理解python类中的方法所需要的参数 self
2017-09-03 21:08
375 查看
1、http://www.cnblogs.com/linuxcat/archive/2012/01/05/2220997.html
self名称不是必须的,在python中self不是关键词,你可以定义成a或b或其它名字都可以,但是约定成俗,不要搞另类,大家会不明白的。下例中将self改为myname一样没有错误:
self指的是类实例对象本身(注意:不是类本身)。
如果self指向类本身,那么当有多个实例对象时,self指向哪一个呢?
2、http://blog.csdn.net/taohuaxinmu123/article/details/38558377
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。
虽然你可以给这个参数任何名称,但是强烈建议你使用self这个名称——其他名称都是不赞成你使用的。使用一个标准的名称有很多优点——你的程序读者可以迅速识别它,如果使用self的话,还有些IDE(集成开发环境)也可以帮助你。
给C++/Java/C#程序员的注释Python中的self等价于C++中的self指针和Java、C#中的this参考。
你一定很奇怪Python如何给self赋值以及为何你不需要给它赋值。举一个例子会使此变得清晰。假如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1,
arg2)的时候,这会由python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。
这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个self参数。
声明add()方法时,若不加self,则提示
TypeError: add() takes exactly 2 arguments (3 given)
File "D:\PythonWorkplace\PythonDemo\Tet.py", line 15, in <module>
test.add(1,3)
错误。
拓展一下:
self在Python里不是关键字。self代表当前对象的地址。self能避免非限定调用造成的全局变量。
self是一种习惯,如上面的程序,把sayHi(self)换成sayHi(fles),同样可以得到正确的输出。
3、http://blog.csdn.net/langb2014/article/details/53158032
Python的self参数有时真让人抓狂,比如,你必须在每一个类的方法里显示定义self,然后,它会霸占不需要它们的地方。
[python] view
plain copy
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
def bar(self,y):
return self.x + y
如果你有C++,Java或其他语言的编程背景,你会觉得 __init__ 和 bar 方法里的self 看起来很多余,Python不是经常吹嘘自己的简答和优雅吗,self到底有什么用?
作用域出现了
在python里,作用域是非常简单的。Python里的一切都是对象,几乎任何东西都是在对象水平的作用域里。写一个模块试试?
[python] view
plain copy
# test.py
def say_hi():
print 'Hi!'
你刚刚创建了一个新的带有say_hi属性的模块对象。
定义一个类?
[python] view
plain copy
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
def bar(self,y):
return self.x + y
你刚刚写了一个带有一些属性的类对象,那些属性是 x,__init__ ,还有 bar。
实例化Foo?
[python] view
plain copy
foo = Foo(5)
你创建了一个带有属性x,__init__ ,和bar的Foo 实例,请记住,foo的三个属性跟Foo的不一样,待会,你就会知道为什么。
上下文就是一切
把Foo拆开:
[python] view
plain copy
def bar(self,y):
return self.x + y
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
bar = bar
先不理bar的第一参数self,如果我们单单把bar看作普通的函数,那么,接下来的就很合理了。
[python] view
plain copy
foo = Foo(5)
print bar(foo,4) == 9
print bar(Foo,0) == 9
好像Foo.bar也可以这么做。
[python] view
plain copy
print Foo.bar(foo,4) == 9
print Foo.bar(Foo,0) == 9
第一行打印出结果True,但第二行就出现了类型错误(TypeError):未绑定的方法bar必须用Foo实例作为第一个参数(出现了不匹配的类型对象)。实例化一个Foo,并且修改bar,把self参数隐藏掉。
[python] view
plain copy
print foo.bar(foo,4) == 9
print foo.bar(foo,0) == 9
两行代码都出现 类型错误(TypeError):bar() 需要两个参数(出现了3个)。为什么是2个,而不是3个?答案即将揭晓。
绑定self
如果你查一下三个bar的类型,你会发现,他们不全都一样。
[python] view
plain copy
print type(bar)
# <type 'function'>
print type(Foo.bar)
# <type 'instancemethod'>
print type(foo.bar)
# <type 'instancemethod'>
把任何函数绑定到一个实例方法对象里,并把它封装在一个实例方法对象里,实例方法就会像胶水一样,粘着类、实例对象和原始的函数,最终它们都绑在一起。
[python] view
plain copy
print Foo.bar.im_class == Foo
print Foo.bar.im_func == bar
print Foo.bar.im_self == None
print foo.bar.im_class == Foo
print foo.bar.im_func == bar
print foo.bar.im_self == foo
可以直截了当地用python写一个实例方法类。
[python] view
plain copy
class myinstancemethod(object):
def __init__(self,func,cls,instance=None):
self.im_func = func
self.im_class = cls
self.im_self = instance
def __call__(_self,*args,**kwargs):
args = list(args)
if _self.im_self is not None:
args.insert(0,_self.im_self)
if len(args) == 0:
raise TypeError("unbound method bar() must be called with Foo instance as first argument (got nothing instead)")
elif not isinstance(args[0],_self.im_class):
raise TypeError("unbound method bar() must be called with Foo instance as first argument (got %s instead)" % type(args[0]).__name__)
else:
return _self.im_func(*args,**kwargs)
myinstancemethod 很正确地模仿了实例方法类,它跟前面的foo.bar 和Foo.bar的表现一样,除了它处理了一点类边缘情况和实例方法调用。
[python] view
plain copy
my_unbound(self=foo,y=4)
# TypeError: bar() got multiple values for keyword argument 'self'
Foo.bar(self=foo,y=4)
# TypeError: bar() got multiple values for keyword argument 'self'
my_bound(self=foo,y=4)
# TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
foo.bar(self=foo,y=4)
# TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
这就是为什么你能够传入bar的引用,而不是传入foo,然后调用foo.bar。
闭包
foo 是一个与Foo完全不同的野兽。Python里的任一个变量都是内存里对象的引用——对象之间都没什么不同。Foo.x,Foo.__init__ 和 Foo.bar这三个与foo.x,foo.__Init__, 和foo.bar不同,他们都指向不同的内存空间。
[python] view
plain copy
print Foo.x is not foo.x
print Foo.__init__ is not foo.__init__
print Foo.bar is not foo.bar
Foo 和foo 是完全不相关的实体,它们只是碰巧在适当的时候相互引用对方。
深入理解python之self
首先明确的是self只有在类的方法中才会有,独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。self名称不是必须的,在python中self不是关键词,你可以定义成a或b或其它名字都可以,但是约定成俗,不要搞另类,大家会不明白的。下例中将self改为myname一样没有错误:
1 class Person: 2 def _init_(myname,name): 3 myname.name=name 4 def sayhello(myname): 5 print 'My name is:',myname.name 6 p=Person('Bill') 7 print p
self指的是类实例对象本身(注意:不是类本身)。
1 class Person: 2 def _init_(self,name): 3 self.name=name 4 def sayhello(self): 5 print 'My name is:',self.name 6 p=Person('Bill') 7 print p
在上述例子中,
self
指向Person的实例p。 为什么不是指向类本身呢,如下例子:
1 class Person: 2 def _init_(self,name): 3 self.name=name 4 def sayhello(self): 5 print 'My name is:',self.name 6 p=Person('Bill') 7 p1 = Person('Apple') 8 print p
如果self指向类本身,那么当有多个实例对象时,self指向哪一个呢?
2、http://blog.csdn.net/taohuaxinmu123/article/details/38558377
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。
虽然你可以给这个参数任何名称,但是强烈建议你使用self这个名称——其他名称都是不赞成你使用的。使用一个标准的名称有很多优点——你的程序读者可以迅速识别它,如果使用self的话,还有些IDE(集成开发环境)也可以帮助你。
给C++/Java/C#程序员的注释Python中的self等价于C++中的self指针和Java、C#中的this参考。
你一定很奇怪Python如何给self赋值以及为何你不需要给它赋值。举一个例子会使此变得清晰。假如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1,
arg2)的时候,这会由python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。
这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个self参数。
声明add()方法时,若不加self,则提示
TypeError: add() takes exactly 2 arguments (3 given)
File "D:\PythonWorkplace\PythonDemo\Tet.py", line 15, in <module>
test.add(1,3)
错误。
拓展一下:
self在Python里不是关键字。self代表当前对象的地址。self能避免非限定调用造成的全局变量。
self是一种习惯,如上面的程序,把sayHi(self)换成sayHi(fles),同样可以得到正确的输出。
3、http://blog.csdn.net/langb2014/article/details/53158032
python中的self理解
(原文是 Python's Magical Self ,来自 http://concentricsky.com )Python的self参数有时真让人抓狂,比如,你必须在每一个类的方法里显示定义self,然后,它会霸占不需要它们的地方。
[python] view
plain copy
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
def bar(self,y):
return self.x + y
如果你有C++,Java或其他语言的编程背景,你会觉得 __init__ 和 bar 方法里的self 看起来很多余,Python不是经常吹嘘自己的简答和优雅吗,self到底有什么用?
作用域出现了
在python里,作用域是非常简单的。Python里的一切都是对象,几乎任何东西都是在对象水平的作用域里。写一个模块试试?
[python] view
plain copy
# test.py
def say_hi():
print 'Hi!'
你刚刚创建了一个新的带有say_hi属性的模块对象。
定义一个类?
[python] view
plain copy
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
def bar(self,y):
return self.x + y
你刚刚写了一个带有一些属性的类对象,那些属性是 x,__init__ ,还有 bar。
实例化Foo?
[python] view
plain copy
foo = Foo(5)
你创建了一个带有属性x,__init__ ,和bar的Foo 实例,请记住,foo的三个属性跟Foo的不一样,待会,你就会知道为什么。
上下文就是一切
把Foo拆开:
[python] view
plain copy
def bar(self,y):
return self.x + y
class Foo(object):
x = 9
def __init__(self,x):
self.x = x
bar = bar
先不理bar的第一参数self,如果我们单单把bar看作普通的函数,那么,接下来的就很合理了。
[python] view
plain copy
foo = Foo(5)
print bar(foo,4) == 9
print bar(Foo,0) == 9
好像Foo.bar也可以这么做。
[python] view
plain copy
print Foo.bar(foo,4) == 9
print Foo.bar(Foo,0) == 9
第一行打印出结果True,但第二行就出现了类型错误(TypeError):未绑定的方法bar必须用Foo实例作为第一个参数(出现了不匹配的类型对象)。实例化一个Foo,并且修改bar,把self参数隐藏掉。
[python] view
plain copy
print foo.bar(foo,4) == 9
print foo.bar(foo,0) == 9
两行代码都出现 类型错误(TypeError):bar() 需要两个参数(出现了3个)。为什么是2个,而不是3个?答案即将揭晓。
绑定self
如果你查一下三个bar的类型,你会发现,他们不全都一样。
[python] view
plain copy
print type(bar)
# <type 'function'>
print type(Foo.bar)
# <type 'instancemethod'>
print type(foo.bar)
# <type 'instancemethod'>
把任何函数绑定到一个实例方法对象里,并把它封装在一个实例方法对象里,实例方法就会像胶水一样,粘着类、实例对象和原始的函数,最终它们都绑在一起。
[python] view
plain copy
print Foo.bar.im_class == Foo
print Foo.bar.im_func == bar
print Foo.bar.im_self == None
print foo.bar.im_class == Foo
print foo.bar.im_func == bar
print foo.bar.im_self == foo
可以直截了当地用python写一个实例方法类。
[python] view
plain copy
class myinstancemethod(object):
def __init__(self,func,cls,instance=None):
self.im_func = func
self.im_class = cls
self.im_self = instance
def __call__(_self,*args,**kwargs):
args = list(args)
if _self.im_self is not None:
args.insert(0,_self.im_self)
if len(args) == 0:
raise TypeError("unbound method bar() must be called with Foo instance as first argument (got nothing instead)")
elif not isinstance(args[0],_self.im_class):
raise TypeError("unbound method bar() must be called with Foo instance as first argument (got %s instead)" % type(args[0]).__name__)
else:
return _self.im_func(*args,**kwargs)
myinstancemethod 很正确地模仿了实例方法类,它跟前面的foo.bar 和Foo.bar的表现一样,除了它处理了一点类边缘情况和实例方法调用。
[python] view
plain copy
my_unbound(self=foo,y=4)
# TypeError: bar() got multiple values for keyword argument 'self'
Foo.bar(self=foo,y=4)
# TypeError: bar() got multiple values for keyword argument 'self'
my_bound(self=foo,y=4)
# TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
foo.bar(self=foo,y=4)
# TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
这就是为什么你能够传入bar的引用,而不是传入foo,然后调用foo.bar。
闭包
foo 是一个与Foo完全不同的野兽。Python里的任一个变量都是内存里对象的引用——对象之间都没什么不同。Foo.x,Foo.__init__ 和 Foo.bar这三个与foo.x,foo.__Init__, 和foo.bar不同,他们都指向不同的内存空间。
[python] view
plain copy
print Foo.x is not foo.x
print Foo.__init__ is not foo.__init__
print Foo.bar is not foo.bar
Foo 和foo 是完全不相关的实体,它们只是碰巧在适当的时候相互引用对方。
相关文章推荐
- 【Python】类的属性和方法的参数加不加self的区别
- Python在定义类方法时为什么要显示声明self参数
- Python3基础 self是什么及其用法 类中大多数方法需要self参数
- 理解 Delphi 的类(十一) - 深入类中的方法[3] - 方法在实现时的参数省略
- python的类方法为什么要写一个self参数
- 为什么Python类的方法需要加self作为第一个参数?
- python @classmethod 和 @staticmethod区别,以及类中方法参数cls和self的区别
- Python入门:自定义类中的方法被调用的时候,什么情况下需要传入self,什么时候不需要
- filter多个参数处理方法+Python的filter过滤器理解
- python 中 类 子类 属性 方法 对象 self 理解
- 理解 Delphi 的类(十一) - 深入类中的方法[10] - 构造方法与析构方法
- 理解 Delphi 的类(十一) - 深入类中的方法[9] - 不能被覆盖的方法与不能被继承的类
- 理解 Delphi 的类(十一) - 深入类中的方法[13] - 方法的调用约定
- 理解 Delphi 的类(十一) - 深入类中的方法[11] - 事件方法
- python 参数列表中的self 显式不等于冗余
- java 方法的形式参数和实际参数的理解
- 理解 Delphi 的类(十一) - 深入类中的方法[8] - 抽象方法与抽象类
- 理解 Delphi 的类(十一) - 深入类中的方法[6] - 类中的方法重载
- 理解 Delphi 的类(十) - 深入方法[21] - 开放数组参数
- 理解 Delphi 的类(十一) - 深入类中的方法[5] - 静态方法、类方法、静态类方法