我有一个来自下面粘贴的boto框架的代码文件,所有的print语句都是我的,而一条注释掉的行也是我的,所有其他属于属性作者。
我的问题是实例化一个类时python中实例化和分配的顺序是什么?下面作者的代码假设在创建类的实例时会存在'DefaultDomainName'(例如调用__init __()),但这似乎不是这种情况,至少在我的python 2.5测试中OS X.
在类Manager __init __()方法中,我的print语句显示为“None”。并且在设置Manager.DefaultDomainName之前,全局函数set_domain()中的print语句向下显示“None”,并在赋值后显示“test_domain”的预期值。但是在调用set_domain()之后再次创建Manager实例时,__ init __()方法仍显示“无”。
任何人都可以帮助我,并解释这里发生了什么。这将不胜感激。谢谢。
# 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
答案 0 :(得分:9)
一些python笔记
当python执行类块时,它会在遇到它时创建该类的所有“属性”。它们通常是类变量以及函数(方法)等。
因此,在类定义中遇到“Manager.DefaultDomainName”时,会设置该值。此代码仅运行一次 - 再也不会。原因是它只是“定义”名为“Manager”的类对象。
当实例化类“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__
请在弄清楚时在这里更新。
答案 1 :(得分:1)
gahooa说的是什么。除此之外,我假设boto.config.get(...)
返回None
,大概是因为default_domain
键未在配置文件的Persist
部分中定义。
boto.config
在boto/__init__.py
中定义为config = boto.pyami.config.Config()
(基本上)。 boto.pyami.config.Config
是标准ConfigParser.SafeConfigParser
的子类,它会在boto.pyami.BotoConfigLocations
指定的位置查找配置文件,默认为包含/etc/boto.cfg
和{{1}的列表}。如果您在其中任何一个位置都没有配置,则您将没有默认域名。
答案 2 :(得分:1)
谢谢大家的帮助。我想出了我所缺少的东西:
我正在使用的boto类的类定义包含Manager的类变量,如果没有Manager传递给这些类的__init__()
,则它们将作为默认值。在导入包含这些类的模块时,我甚至没有想到这些类变量将使用import语句进行评估。
因此,在我甚至调用set_domain()
之前,这些类变量Managers的self.domain_name值是从DefaultDomainName设置的,因为我没有像ruds指出的那样设置配置文件,所以该值为None。
所以,我必须稍微修改我的代码,但是谢谢你们帮助一个python新手。
答案 3 :(得分:0)
当你加载模块时,python逐行执行每个代码。由于代码被执行,所以类变量都应该在加载时设置。很可能你的boto.config.get函数刚刚返回None。换句话说,是的,所有类变量都是在实例变量之前分配的。