ric*_*lla 1061 python oop class self
selfPython 中这个词的目的是什么?我理解它指的是从该类创建的特定对象,但我不明白为什么它明确需要作为参数添加到每个函数.为了说明,在Ruby中我可以这样做:
class myClass
def myFunc(name)
@name = name
end
end
Run Code Online (Sandbox Code Playgroud)
我很容易理解.但是在Python中我需要包括self:
class myClass:
def myFunc(self, name):
self.name = name
Run Code Online (Sandbox Code Playgroud)
谁能跟我说说这个?这不是我在(无可否认的有限)经历中遇到的事情.
Tho*_*ers 679
您需要使用的原因self.是因为Python不使用@语法来引用实例属性.Python的决定做方法的方式,使该实例该方法属于可通过自动,但不接受自动:方法的第一个参数是实例的方法被调用.这使方法与函数完全相同,并留下实际名称以供您使用(虽然self是惯例,当您使用其他东西时,人们通常会对您不满.)self对代码来说并不特殊,它只是另一个对象.
Python可以做其他事情来区分普通名称和属性 - 像Ruby这样的特殊语法,或者需要像C++和Java那样的声明,或者可能是更不同的东西 - 但事实并非如此.Python的所有内容都是为了使事情变得明确,让它显而易见的是什么,虽然它并不是完全无处不在,但它确实是为了实例属性.这就是为什么分配一个实例属性需要知道要分配的实例,这就是它需要的原因self..
Deb*_*ski 412
我们来看一个简单的矢量类:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
Run Code Online (Sandbox Code Playgroud)
我们想要一个计算长度的方法.如果我们想在类中定义它会是什么样子?
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
Run Code Online (Sandbox Code Playgroud)
当我们将其定义为全局方法/函数时,它应该是什么样的?
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
Run Code Online (Sandbox Code Playgroud)
所以整个结构保持不变.我怎么能利用这个呢?如果我们假设我们没有length为我们的Vector类编写方法,我们可以这样做:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
Run Code Online (Sandbox Code Playgroud)
这是因为第一个参数length_global,可以重新用作self参数length_new.如果没有明确的话,这是不可能的self.
理解显式需求的另一种方法self是查看Python添加一些语法糖的位置.当你记住,基本上,一个电话就像
v_instance.length()
Run Code Online (Sandbox Code Playgroud)
内部转变为
Vector.length(v_instance)
Run Code Online (Sandbox Code Playgroud)
很容易看到self适合的位置.你实际上并没有在Python中编写实例方法; 你写的是类方法,它必须将实例作为第一个参数.因此,您必须明确地将实例参数放在某处.
Arj*_*ran 374
假设您有一个类ClassA,其中包含一个methodA定义为的方法:
def methodA(self, arg1, arg2):
# do something
Run Code Online (Sandbox Code Playgroud)
并且ObjectA是这个类的一个实例.
现在ObjectA.methodA(arg1, arg2)调用时,python会在内部将其转换为:
ClassA.methodA(ObjectA, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)
的self变量是指对象本身.
sw1*_*456 207
实例化对象时,对象本身将传递给self参数.

因此,对象的数据绑定到对象.下面是一个示例,说明如何可视化每个对象的数据外观.注意如何用对象名称替换"self".我不是说下面的这个示例图是完全准确的,但它有望用于可视化自我的使用.

Object被传递给self参数,以便对象可以保持自己的数据.
虽然这可能不完全准确,但请考虑实例化这样的对象的过程:当一个对象被创建时,它使用该类作为其自己的数据和方法的模板.如果不将自己的名称传递给self参数,则类中的属性和方法将保留为通用模板,并且不会引用(属于)对象.因此,通过将对象的名称传递给self参数,意味着如果从一个类中实例化100个对象,则它们都可以跟踪自己的数据和方法.
见下图:

kam*_*ame 76
我喜欢这个例子:
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: []
Run Code Online (Sandbox Code Playgroud)
nin*_*cko 38
我将演示不使用类的代码:
def state_init(state):
state['field'] = 'init'
def state_add(state, x):
state['field'] += x
def state_mult(state, x):
state['field'] *= x
def state_getField(state):
return state['field']
myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)
print( state_getField(myself) )
#--> 'initaddedinitadded'
Run Code Online (Sandbox Code Playgroud)
类只是一种避免一直传递这种"状态"的东西的方法(以及其他很好的东西,比如初始化,类组合,很少需要的元类,以及支持自定义方法来覆盖运算符).
现在让我们使用内置的python类机器演示上面的代码,以显示它是如何基本相同的.
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 )
Run Code Online (Sandbox Code Playgroud)
[从重复的封闭问题中移出我的答案]
Mat*_*kin 19
与Modula-3一样,[在Python中]没有用于从其方法引用对象成员的简写:方法函数使用表示对象的显式第一个参数声明,该参数由调用隐式提供.
通常,方法的第一个参数称为self.这只不过是一个惯例:名称self对Python来说绝对没有特殊意义.但是请注意,如果不遵循惯例,您的代码可能对其他Python程序员来说可读性较低,并且可以想象可能会编写依赖于此类约定的类浏览器程序.
有关更多信息,请参阅有关类的Python文档教程.
Pon*_*dle 19
除了已经说明的所有其他原因之外,它还允许更容易地访问被覆盖的方法; 你可以打电话Class.some_method(inst).
它有用的一个例子:
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
Run Code Online (Sandbox Code Playgroud)
>>> C2()
"C2 init"
"C1 init"
Run Code Online (Sandbox Code Playgroud)
小智 15
它的用法类似于this在Java中使用关键字,即提供对当前对象的引用.
ytp*_*lai 14
Python不是为面向对象编程而构建的语言,与Java或C++不同.
在Python中调用静态方法时,只需在其中编写一个带有常规参数的方法.
class Animal():
def staticMethod():
print "This is a static method"
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,需要您创建变量的对象方法需要self参数
class Animal():
def objectMethod(self):
print "This is an object method which needs an instance of a class"
Run Code Online (Sandbox Code Playgroud)
self方法还用于引用类中的变量字段.
class Animal():
#animalName made in constructor
def Animal(self):
self.animalName = "";
def getAnimalName(self):
return self.animalName
Run Code Online (Sandbox Code Playgroud)
在这种情况下,self指的是整个类的animalName变量.记住:如果方法中有变量,则self不起作用.该变量仅在该方法运行时存在.对于定义字段(整个类的变量),您必须在类方法外定义它们.
如果你不理解我所说的单词,那么Google就是"面向对象的编程".一旦你理解了这一点,你甚至不需要问这个问题:).
它遵循Python zen"显然优于隐式".它确实是对您的类对象的引用.例如,在Java和PHP中,它被称为this.
如果user_type_name是模型上的字段,则可以访问它self.user_type_name.
看看下面的例子,它清楚地解释了 self
class Restaurant(object):
bankrupt = False
def open_branch(self):
if not 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
Run Code Online (Sandbox Code Playgroud)
self 用于/需要区分实例。
来源:python 中的 self 变量解释 - Pythontips
首先,自我是一个传统的名称,你可以把任何其他东西(连贯的)代替.
它指的是对象本身,因此当您使用它时,您声明.name和.age是您要创建的Student对象(注意,而不是Student类)的属性.
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
Run Code Online (Sandbox Code Playgroud)
使用通常称为“参数”的self方法并不难理解,因为为什么有必要?还是至于为什么要明确提及呢?我想,对于大多数查询此问题的用户来说,这是一个更大的问题,或者如果不是,则在继续学习python时,他们肯定会有相同的问题。我建议他们阅读以下两个博客:
请注意,它不是关键字。
每个类方法(包括init)的第一个参数始终是对当前类实例的引用。按照惯例,此参数始终命名为self。在init方法中,self指的是新创建的对象;在其他类方法中,它引用其方法被调用的实例。例如,下面的代码与上面的代码相同。
2:为什么要用这种方式,为什么不能像Java那样将其作为参数消除,而要用关键字代替
我想添加的另一件事是,可选self参数允许我通过不编写来在类内声明静态方法self。
代码示例:
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"
Run Code Online (Sandbox Code Playgroud)
PS:仅在Python 3.x中有效。
在以前的版本中,必须显式添加@staticmethod装饰器,否则self必须使用参数。
我很惊讶没有人提出Lua。Lua也使用'self'变量,但是可以省略但仍然使用。C ++对“ this”的作用相同。我没有看到任何理由必须在每个函数中声明'self',但是您仍然应该能够像在lua和C ++中一样使用它。对于一种以简短为荣的语言,奇怪的是它要求您声明自变量。
是因为按照 python 的设计方式,替代方案几乎不起作用。Python 旨在允许在隐式this(a-la Java/C++)或显式@(a-la ruby)都不起作用的上下文中定义方法或函数。让我们举一个使用 python 约定的显式方法的例子:
def fubar(x):
self.x = x
class C:
frob = fubar
Run Code Online (Sandbox Code Playgroud)
现在该fubar函数将无法工作,因为它假定这self是一个全局变量(以及 in frob)。另一种方法是使用替换的全局范围(self对象在哪里)来执行方法。
隐式方法是
def fubar(x)
myX = x
class C:
frob = fubar
Run Code Online (Sandbox Code Playgroud)
这意味着myX将被解释为 in fubar(以及 in frob)的局部变量。此处的替代方法是使用在调用之间保留的替换局部作用域来执行方法,但这将消除方法局部变量的可能性。
然而,目前的情况很好:
def fubar(self, x)
self.x = x
class C:
frob = fubar
Run Code Online (Sandbox Code Playgroud)
这里的时候,被称为一方法frob将接收上它通过调用对象self的参数,并且fubar仍然可以用一个对象作为参数调用和工作一样(这是一样的C.frob,我认为)。
| 归档时间: |
|
| 查看次数: |
807848 次 |
| 最近记录: |