簡體   English   中英

將類實例化為可迭代

[英]Instantiate a Class as an Iterable

我有一個要實例化的類,然后傳遞給Tornado Web模板。 這兩個函數都返回一個列表,但是在使Class本身成為可迭代對象時,我缺少一些東西。 恐怕這是我做錯了的基本事情。 我正在進行REST API調用,解析返回的XML,並將一些數據返回到webapp。 這是代碼:

API調用:

class GetVMList:

    def __init__(self):
        user = 'contoso\\administrator'
        password = "apassword"
        url = "http://scspf:8090/SC2012/VMM/Microsoft.Management.Odata.svc/VirtualMachines?$filter=VMMServer%20eq%20'scvmm'"

        passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
        passman.add_password(None, url, user, password)
        # create the NTLM authentication handler
        auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)

        # create and install the opener
        opener = urllib2.build_opener(auth_NTLM)
        urllib2.install_opener(opener)

        # retrieve the result
        self.response = urllib2.urlopen(url)
        self.data = self.response.read()

    def name(self):
        dom = parseString(self.data)
        raw_xml = dom.getElementsByTagName('d:Name')
        clean_xml = []
        clean_data = []
        for i in raw_xml:
            clean_xml.append(i.toxml())
        for i in clean_xml:
            clean_data.append(i.replace('<d:Name>', '').replace('</d:Name>', ''))
        return clean_data

    def os(self):
        dom = parseString(self.data)
        raw_xml = dom.getElementsByTagName('d:OperatingSystem')
        clean_xml = []
        clean_data = []
        for i in raw_xml:
            clean_xml.append(i.toxml())
        for i in clean_xml:
            clean_data.append(i.replace('<d:OperatingSystem>', '').replace('</d:OperatingSystem>', ''))
        return clean_data

實例化:

class ListHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('temp/search.html', data='')

    def post(self):
        vm_list = GetVMList()
        self.render('temp/search.html', data=vm_list)

然后模板包含以下內容:

{% for vm in data %}
<li>{{ vm.name }} running {{ vm.os }}</li>
{% end %}

錯誤是: TypeError: iteration over non-sequence 我想我需要在課堂上使用__iter__ ,但是我不確定我是否確切了解它是如何工作的。

我相信您在課堂上缺少__iter__的定義。

我的建議如下:

  1. 創建一個類VM用於存儲有關單個虛擬機的信息。 它的__init__應該獲取您要存儲的有關每個VM的信息,並將其設置為實例上的屬性。 如果不需要任何實際代碼來處理有關VM的數據,則可以使用collections.namedtuple ,這樣可以省去編寫__init__()方法的__init__()

  2. getVMs()作為生成器編寫,給定用戶,密碼和URL,生成一系列VM實例。 此結果可以按原樣進行迭代,或者可以輕松轉換為常規列表(如果需要)(只需將其傳遞給list() ),或用於創建將VM名稱映射到OS的字典(反之亦然)。

例如(此代碼未經測試):

class VM(object):
    def __init__(self, name, os):
        self.name = name
        self.os   = os

def getVMs(user, password, URL):
    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passman.add_password(None, url, user, password)
    auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)
    urllib2.install_opener(urllib2.build_opener(auth_NTLM))
    dom = parseString(urllib2.urlopen(url).read())
    for vmnode in dom.getElementsByTagName('d:VM')   # the tag representing a VM
        name = vmnode.getElementsByTagName('d:Name')[0]  # get name of current VM
        name = name.replace('<d:Name>', '').replace('</d:Name>', '')
        os = vmnode.getElementsByTagName('d:OperatingSystem')[0]   # same for OS
        os = os.replace('<d:OperatingSystem>', '').replace('</d:OperatingSystem>', ''))
        yield VM(name, os)

...您還可以為您的VM對象提供名稱和OS的XML或整個VM的XML,但是此示例實現僅將名稱和OS作為字符串。

(有更好的方法來獲取DOM節點的內容,而不必使用空白字符串替換XML標簽,但是我現在沒有時間這樣做。)

調用它:

user = r"contoso\administrator"
pass = "apassword"
url  = ("http://scspf:8090/SC2012/VMM/Microsoft.Management.Odata.svc"
        "/VirtualMachines?$filter=VMMServer%20eq%20'scvmm'")

vmlist = list(getVMs(user, pass, url))

或僅打印每個VM的信息而不存儲中間列表:

for vm in getVMs(user, pass, url):
    print vm.name, vm.os

或為VM實例構建名稱的字典(假定具有dict理解的Python的最新版本):

vmdict = {vm.name: vm for vm in getVMs(user, pass, url)}

使用生成器模型使其對於調用者具有最大的靈活性。 即使該呼叫者是您,也將使您的生活更輕松。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM