首页 > 解决方案 > 我在实例化过程中传递给类的参数/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/')

DEBUG:是的,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) 函数接收 kwargs 的:

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))

DEBUG:以下是 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 参数?

标签: pythonclassoopkeyword-argument

解决方案


这是因为当您编写 时Class(a, b),它会将 和 的值传递给在该类(或函数)上定义为前两个名称的任何名称。ab

但是当您说 时Class(a=a, b=b),您是在说“Class.__init__使用aset toa (from my scope)和 set bto调用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)

*将表明剩余的参数不能在位置上指定,必须用名称表示。

老实说,在我得到提示之前,我也被这个问题难住了。


推荐阅读