类实例化和';自我';用python

类实例化和';自我';用python,python,class,function,instantiation,self,Python,Class,Function,Instantiation,Self,我知道关于这个问题已经写了很多。然而,我不能吸收太多。也许是因为我是一个完全的新手,在没有任何计算机科学培训的情况下自学。不管怎样,如果你们中的一些大智若愚的人加入到这个特定的例子中,也许你们会帮助像我这样的初学者 因此,我编写了以下函数,当我调用它(作为一个模块?)作为它自己的名为“funky.py”的文件时,它工作得很好: 我在终端中键入以下内容: python classy.py 而且运行良好 def load_deck(): suite = ('Spades', 'Hearts

我知道关于这个问题已经写了很多。然而,我不能吸收太多。也许是因为我是一个完全的新手,在没有任何计算机科学培训的情况下自学。不管怎样,如果你们中的一些大智若愚的人加入到这个特定的例子中,也许你们会帮助像我这样的初学者

因此,我编写了以下函数,当我调用它(作为一个模块?)作为它自己的名为“funky.py”的文件时,它工作得很好:

我在终端中键入以下内容:

python classy.py
而且运行良好

def load_deck():
    suite = ('Spades', 'Hearts')
    rank = ('2', '3')
    full_deck = {}
    i = 0
    for s in suite:
        for r in rank:
            full_deck[i] = "%s of %s" % (r, s)
            i += 1
    return full_deck

print load_deck()
然而,当我将相同的函数放入一个类中时,我得到了一个错误

这是我的“classy.py”代码:

class GAME():
    def load_deck():
        suite = ('Spades', 'Hearts')
        rank = ('2', '3')
        full_deck = {}
        i = 0
        for s in suite:
            for r in rank:
                full_deck[i] = "%s of %s" % (r, s)
                i += 1
        return full_deck
MyGame = GAME()
print MyGame.load_deck()
我得到以下错误:

Traceback (most recent call last):
File "classy.py", line 15, in <module>
print MyGame.load_deck()
TypeError: load_deck() takes no arguments (1 given)
将一个函数放入一个需要使用“self”的类中是什么。我明白“自我”只是一种惯例。那么,为什么需要争论呢?从类中调用函数时,函数的行为是否不同

而且,这几乎更重要,为什么我的课堂没有使用init?使用init对我的课堂有什么作用


基本上,如果有人有时间像我6岁那样向我解释这一点,这会有所帮助。提前感谢您的帮助。

在类定义中定义函数会调用一些魔法,将其转换为方法描述符。当您访问foo.method时,它将自动创建绑定方法并将对象实例作为第一个参数传递。您可以通过使用@staticmethod装饰器来避免这种情况

\uuuu init\uuuu
只是在创建类以执行可选设置时调用的方法<代码>\uuuu新建\uuuu是实际创建对象的内容

这里有一些例子

>>> class Foo(object):
    def bar(*args, **kwargs):
        print args, kwargs

>>> foo = Foo()
>>> foo.bar
<bound method Foo.bar of <__main__.Foo object at 0x01C9FEB0>>
>>> Foo.bar
<unbound method Foo.bar>
>>> foo.bar()
(<__main__.Foo object at 0x01C9FEB0>,) {}
>>> Foo.bar()

Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module>
    Foo.bar()
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
>>> Foo.bar(foo)
(<__main__.Foo object at 0x01C9FEB0>,) {}
>>类Foo(对象):
定义栏(*args,**kwargs):
打印args,kwargs
>>>foo=foo()
>>>美食酒吧
>>>美食酒吧
>>>foo.bar()
(,) {}
>>>Foo.bar()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
Foo.bar()
TypeError:必须使用Foo实例作为第一个参数调用unbound方法bar()(但没有得到任何结果)
>>>Foo.bar(Foo)
(,) {}
那么,为什么需要争论呢

访问类的当前实例上的属性

假设您有一个具有两种方法的类,
load\u deck
shuffle
。在
load_-deck
的末尾,您希望洗牌(通过调用
shuffle
方法)

在Python中,您可以执行以下操作:

class Game(object):
    def shuffle(self, deck):
        return random.shuffle(deck)

    def load_deck(self):
        # ...

        return self.shuffle(full_deck)

将其与大致等同的C++代码进行比较:

class Game {
    shuffle(deck) {
        return random.shuffle(deck);
    }
    load_deck() {
        // ...

        return shuffle(full_deck)
    }
}
shuffle(full_-deck)
行中,它首先查找名为
shuffle
的局部变量-该变量不存在,然后检查更高一级,并找到名为
shuffle
的实例方法(如果不存在,它将检查具有正确名称的全局变量)

这没关系,但不清楚shuffle是指某个局部变量还是实例方法。为了解决这种模糊性,还可以通过
this
访问实例方法或实例属性:

...
load_deck() {
    // ...

    return this->shuffle(full_deck)
}
这个
与Python本身几乎相同,只是它没有作为参数传递

为什么将
self
作为有用的参数是有用的这些可通过以下行进行总结:

这是由博客中的一篇文章支持的

我决定放弃隐式引用实例变量的想法。像C++这样的语言让你写这个-> FO来显式引用实例变量FO(如果有单独的局部变量FO)。因此,我决定将这种显式引用作为引用实例变量的唯一方法。此外,我决定不将当前对象(“this”)作为一个特殊的关键字,而是将“this”(或其等价物)作为方法的第一个命名参数。实例变量总是作为该参数的属性引用

对于显式引用,不需要为方法定义使用特殊语法,也不必担心变量查找的复杂语义。相反,我们只需定义一个函数,其第一个参数对应于实例,按照惯例称之为“self”


如果您不打算使用self,您可能应该将该方法声明为静态方法

class Game:
    @staticmethod
    def load_deck():
        ....
这将撤消自动默认打包,该打包通常会将范围中的函数转换为以实例为参数的方法

传递您不使用的参数会让其他试图阅读您的代码的人感到不安

大多数班级都有成员。你的不是,所以它的所有方法都应该是静态的。随着项目的发展,您可能会发现其中所有功能都可以访问的数据,您会将这些数据放入self,并将其传递给所有功能

在此上下文中,应用程序本身是您的主要对象,\uuu init\uuu只是初始化所有这些共享值的函数


这是迈向面向对象风格的第一步,在这种风格中,较小的数据片段被用作对象本身。但这是从直接脚本到OO编程的正常阶段。

主要的一点是,一个类有许多实例-您需要
self
知道您正在处理哪个实例。如果你不需要很多实例,你应该问问自己是否需要一个类。这是一个开始。什么是边界方法?将对象实例作为第一个参数传递意味着什么?这是否意味着函数将函数本身作为第一个参数传递?传给什么?还有,为什么?写“self”能解决什么问题?绑定方法意味着对象实例已经作为第一个参数传递。你可以把它想象成一只羔羊。一个未绑定的方法就是当你
Explicit is better than implicit.
class Game:
    @staticmethod
    def load_deck():
        ....