我在实例化__init__期间传递给类的参数/参数被忽略

时间:2018-07-17 14:49:16

标签: python class oop kwargs

我无法理解为什么该类对象不使用我的 init 参数。这是python 3.6。

在一个文件中,我导入一个网络爬虫并将kwargs传递到其中:

import metacrawler as mc
mc.crawlwrapper(url=archive_url, archive_org=True, index_pages=True, depth_limit=2, fileroot='content/')

调试:是的,此时True参数定义为True

{'archive_org': True}

进入创建类实例的中间函数。这是介于中间的函数,用于解析从第一个函数到Crawler的所有内容:

def crawlwrapper(**kw):
    fileroot = kw.get('fileroot','')
    url = kw['url']
    print('DEBUG(pre):{0}'.format(kw))
    depth_limit = kw.get('depth_limit',3)
    confine_prefix= kw.get('confine_prefix') # use to make archive.org not follow external links
    archive_org = kw.get('archive_org',False) # special urlparse rules apply
    exclude=kw.get('exclude',[])
    print_pov=kw.get('print_pov',False)    
    index_pages = kw.get('index_pages')    
    print('DEBUG(post): depth_limit, confine_prefix, index_pages, archive_org {0}'.format([depth_limit, confine_prefix, index_pages, archive_org]))

    crawler = Crawler(url, depth_limit, confine_prefix, exclude, index_pages, print_pov, archive_org)
    crawler.crawl()

这里是Crawler,它从crawlwrapper(** kw)函数接收kwarg:

class Crawler(object):
    ##BUG: for some reason, at some point, the init defaults don't get overridden when instatiated.

    def __init__(self, url, depth_limit, confine=None, exclude=[], locked=True, filter_seen=True, index_pages=True, print_pov=False, archive_org=None):
        print('depth_limit {0}, confine {1}, index_pages {2}, archive_org {3}'.format(depth_limit, confine, index_pages, archive_org))

调试:这是crawler.crawl()类方法中收到的内容:

depth_limit 2, confine http://www.cfu.or.ug, index_pages True, archive_org None

是否注意到achive_org从True更改为None

为什么Crawler没有收到我的archive_org = True参数?

1 个答案:

答案 0 :(得分:2)

这是因为当您编写Class(a, b)时,它会将ab values 传递给该类中定义为前两个名称的任何名称(或功能)。

但是当您说Class(a=a, b=b)时,您是说“在Class.__init__设置为a并将a (from my scope)设置为b的情况下呼叫b (from my scope)

您在第一次通话中写的内容等同于crawler = Crawler(root=url, depth_limit=depth_limit, confine=confine_prefix, exclude=exclude, locked=index_pages, filter_seen=print_pov, index_pages=archive_org, print_pov=False, archive_org=None)

换句话说,调用者的名称空间/范围和被调用的函数/方法的签名之间没有隐式关系。除非您使用关键字参数(a=a),否则参数是按位置分配的。

Python 3添加了对仅关键字参数的支持,这可能有助于防止这种情况。您是否这样定义了Crawler.__init__

def __init__(self, root, depth_limit, *, confine=None, exclude=[], locked=True, filter_seen=True, index_pages=True, print_pov=False, archive_org=None)

*表示无法在位置上指定其余参数,而必须用名称表示。

老实说,直到我得到提示为止,我也为这个问题感到困惑。