Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python类是如何工作的?_Python - Fatal编程技术网

python类是如何工作的?

python类是如何工作的?,python,Python,我有一个来自boto框架的代码文件粘贴在下面,所有的打印语句都是我的,注释掉的那一行也是我的,其他的都属于作者 我的问题是,在python中实例化类时,实例化和分配的顺序是什么?下面作者的代码假设在创建类的实例时会存在“DefaultDomainName”(例如,调用了__init__()),但情况似乎并非如此,至少在我在OS X上用python 2.5进行的测试中是如此 在类管理器init()方法中,我的print语句显示为“None”。全局函数set_domain()中的print语句在设置

我有一个来自boto框架的代码文件粘贴在下面,所有的打印语句都是我的,注释掉的那一行也是我的,其他的都属于作者

我的问题是,在python中实例化类时,实例化和分配的顺序是什么?下面作者的代码假设在创建类的实例时会存在“DefaultDomainName”(例如,调用了__init__()),但情况似乎并非如此,至少在我在OS X上用python 2.5进行的测试中是如此

在类管理器init()方法中,我的print语句显示为“None”。全局函数set_domain()中的print语句在设置Manager.DefaultDomainName之前显示“None”,并在赋值之后显示“test_domain”的预期值。但是,在调用set_domain()后再次创建Manager实例时,uuu init_uuuu()方法仍然显示“None”

有人能帮我解释一下这里发生了什么吗。我们将不胜感激。多谢各位



# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import boto
from boto.utils import find_class

class Manager(object):

    DefaultDomainName = boto.config.get('Persist', 'default_domain', None)

    def __init__(self, domain_name=None, aws_access_key_id=None, aws_secret_access_key=None, debug=0):
        self.domain_name = domain_name
        self.aws_access_key_id = aws_access_key_id
        self.aws_secret_access_key = aws_secret_access_key
        self.domain = None
        self.sdb = None
        self.s3 = None
        if not self.domain_name:
            print "1: %s" % self.DefaultDomainName
            print "2: %s" % Manager.DefaultDomainName
            self.domain_name = self.DefaultDomainName
            #self.domain_name = 'test_domain'
            if self.domain_name:
                boto.log.info('No SimpleDB domain set, using default_domain: %s' % self.domain_name)
            else:
                boto.log.warning('No SimpleDB domain set, persistance is disabled')
        if self.domain_name:
            self.sdb = boto.connect_sdb(aws_access_key_id=self.aws_access_key_id,
                                        aws_secret_access_key=self.aws_secret_access_key,
                                        debug=debug)
            self.domain = self.sdb.lookup(self.domain_name)
            if not self.domain:
                self.domain = self.sdb.create_domain(self.domain_name)

    def get_s3_connection(self):
        if not self.s3:
            self.s3 = boto.connect_s3(self.aws_access_key_id, self.aws_secret_access_key)
        return self.s3

def get_manager(domain_name=None, aws_access_key_id=None, aws_secret_access_key=None, debug=0):
    return Manager(domain_name, aws_access_key_id, aws_secret_access_key, debug=debug)

def set_domain(domain_name):
    print "3: %s" % Manager.DefaultDomainName
    Manager.DefaultDomainName = domain_name
    print "4: %s" % Manager.DefaultDomainName

def get_domain():
    return Manager.DefaultDomainName

def revive_object_from_id(id, manager):
    if not manager.domain:
        return None
    attrs = manager.domain.get_attributes(id, ['__module__', '__type__', '__lineage__'])
    try:
        cls = find_class(attrs['__module__'], attrs['__type__'])
        return cls(id, manager=manager)
    except ImportError:
        return None

def object_lister(cls, query_lister, manager):
    for item in query_lister:
        if cls:
            yield cls(item.name)
        else:
            o = revive_object_from_id(item.name, manager)
            if o:
                yield o

一些python注释

当python执行块时,它会在遇到该类时创建该类的所有“属性”。它们通常是类变量以及函数(方法)等

因此,“Manager.DefaultDomainName”的值是在类定义中遇到时设置的。此代码只运行过一次,以后不再运行。原因是它只是“定义”名为“管理器”的类对象

实例化类“Manager”的对象时,它是“Manager”类的实例。(这听起来可能重复)。非常清楚的是,该值:

self.DefaultDomainName
不存在。按照类的规则,python说“嗯,这个对象实例上不存在这样的对象,我来看看类对象”。因此python实际上在以下位置找到值:

Manager.DefaultDomainName

# also referenced by
self.__class__.DefaultDomainName
所有这些都是为了举例说明类属性“Manager.DefaultDomainName”只创建一次,只能存在一次,并且一次只能保存一个值


在上面的示例中,对每个值运行内置函数id():

print "1: %s" % id(self.DefaultDomainName)
print "2: %s" % id(Manager.DefaultDomainName)
您应该看到它们引用的是完全相同的内存位置


现在,在对原始问题的(非)回答中…我不知道如何阅读上面的代码。我建议您尝试几种技巧来找到答案:

# Debug with pdb.  Follow every step of the process to ensure that you are 
# setting valeus as you thought, and that the code you thought would be 
# called is actually being called.  I've had many problems like this where 
# the error was in procedure, not in the actual code at hand.
import pdb; pdb.set_trace()

# check to see if id(Manager) is the same as id(self.__class__)

# in the set_domain() function:
# check to see what attributes you can see on Manager, 
# and if they match the attributes on Manager and self.__class__ in __init__

当你弄明白后,请在此更新。

gahooa说的话。除此之外,我假设
boto.config.get(…)
返回
None
,可能是因为配置文件的
Persist
部分没有定义
default\u domain


boto.config
boto/\uuu init\uuuu.py
中定义为
config=boto.pyami.config()
(本质上)
boto.pyami.config.config
是该标准的一个子类,它在
boto.pyami.BotoConfigLocations
指定的位置查找配置文件,该位置默认为包含
/etc/boto.cfg
$HOME/.boto
的列表。如果在这两个位置中都没有配置,则不会有默认域名。

加载模块时,python会逐行执行每个代码。因为代码是执行的,所以类变量都应该在加载时设置。很可能您的boto.config.get函数刚刚返回None。换句话说,是的,所有类变量都在实例变量之前分配。

谢谢大家的帮助。我发现我错过了什么:

我正在使用的boto类的类定义包含Manager的类变量,如果没有Manager被传递到这些类的
\uuuu init\uuuu()
,则这些类变量将作为默认值。我甚至没有想到,在导入包含这些类的模块时,这些类变量将使用import语句进行计算

因此,这些类变量管理器的self.domain_name值是在我调用
set_domain()
之前从DefaultDomainName设置的,因为我没有如ruds所指出的那样设置配置文件,所以该值为零


因此,我必须稍微修改一下我的代码,但感谢大家帮助一位python新手。

您能发布用于创建Manager对象和设置域的(最小)代码吗?@Miles+1。。。巨大的版权块意味着您必须滚动才能看到代码,而且(您会注意到屏幕底部的小CC徽标)完全没有必要。您不需要发布许可证(也可能无法强制执行许可证)。