代码之家  ›  专栏  ›  技术社区  ›  Mark

python类是如何工作的?

  •  4
  • Mark  · 技术社区  · 15 年前

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

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

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

    
    
    # 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
    
    
    4 回复  |  直到 15 年前
        1
  •  9
  •   gahooa    15 年前

    一些python注释

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

    因此,“Manager.DefaultDomainName”的值是在类定义中遇到时设置的。这个代码是 只跑一次

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

    self.DefaultDomainName
    

    Manager.DefaultDomainName
    
    # also referenced by
    self.__class__.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__
    

    当你弄明白的时候,请在这里更新。

        2
  •  1
  •   ruds    15 年前

    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 $HOME/.boto . 如果您在这两个位置中都没有配置,您就不会有默认域名。

        3
  •  1
  •   S.Lott    15 年前

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

    我使用的boto类的类定义包含Manager的类变量,如果没有Manager传递给 __init__() 这些班级的学生。我甚至没有想到,在导入包含这些类的模块时,这些类变量将使用import语句进行计算。

    set_domain() ,并且由于我没有像ruds指出的那样设置配置文件,所以该值为None。

        4
  •  0
  •   jimx    15 年前

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