2

質問:インスタンス化を強制終了したり、Pythonユニバーサルフィードパーサーの新しいインスタンス化を作成していることを確認するにはどうすればよいですか?


情報:

私は現在、多数のブログをダウンロードしてカタログ化するプログラムに取り組んでいます。不幸なバグを除いて、それはうまく機能しました。私のコードは、ブログのURLのリストを取得し、それらをforループで実行するように設定されています。実行するたびにURLが選択され、データのダウンロード、抽出、およびファイルへの保存を管理する別のクラスに送信されます。

最初のURLは問題なく機能します。ブログ全体をダウンロードしてファイルに保存します。しかし、ダウンロードする2番目のブログには、最初のブログのすべてのデータも含まれているので、理由はまったくわかりません。


コードスニペット:

class BlogHarvester:
  def __init__(self,folder):
    f = open(folder,'r')
    stop = folder[len(folder)-1]
    while stop != '/':
        folder = folder[0:len(folder)-1]
        stop = folder[len(folder)-1]
    blogs = []
    for line in f:
        blogs.append(line)

    for herf in blogs:
        blog = BlogParser(herf)
        sPath = ""
        uid = newguid()##returns random hash.
        sPath = uid
        sPath = sPath + " - " + blog.posts[0].author[1:5] + ".blog"
        print sPath
        blog.storeAsFile(sPath)

class BlogParser:
  def __init__(self, blogherf='null', path='null', posts = []):
    self.blogherf = blogherf

    self.blog = feedparser.parse(blogherf)
    self.path = path
    self.posts = posts
    if blogherf != 'null':
        self.makeList()
    elif path != 'null':
        self.loadFromFile()

class BlogPeices:
  def __init__(self,title,author,post,date,publisher,rights,comments):
    self.author = author
    self.title = title
    self.post = post
    self.date = date
    self.publisher = publisher
    self.rights = rights
    self.comments = comments

おそらく役立つと思われるスニペットを含めました。紛らわしいアーティファクトがある場合は申し訳ありません。このプログラムはお尻の痛みでした。

4

2 に答える 2

1

問題はposts=[]です。デフォルトの引数は実行時ではなくコンパイル時に計算されるため、オブジェクトへの変更はクラスの存続期間中残ります。代わりに、以下を使用posts=Noneしてテストします。

if posts is None:
  self.posts = []
于 2010-01-17T05:28:10.747 に答える
0

Ignacio が言ったように、関数リストのデフォルト引数に発生する変更は、クラスの存続期間中残ります。

http://docs.python.org/reference/compound_stmts.html#function-definitionsから

関数定義が実行されると、デフォルトのパラメータ値が評価されます。これは、関数が定義されるときに式が一度評価され、その同じ「事前計算された」値が各呼び出しに使用されることを意味します。これは、既定のパラメーターがリストや辞書などの変更可能なオブジェクトである場合に特に重要です。関数がオブジェクトを変更する場合 (たとえば、項目をリストに追加することによって)、既定値は事実上変更されます。これは通常、意図したものではありません。これを回避する方法は、None をデフォルトとして使用し、関数の本体で明示的にテストすることです。

しかし、これは一種の落とし穴をもたらします。参照を変更しています...したがって、変更されるとは予想されなかったクラスの消費者のリストを変更している可能性があります。

例えば:

class A:
  def foo(self, x = [] ):
    x.append(1)
    self.x = x

a = A()
a.foo()
print a.x
# prints: [1]
a.foo()
print a.x
# prints: [1,1]   # !!!! Consumer would expect this to be [1]
y = [1,2,3]
a.foo(y)
print a.x
# prints: [1, 2, 3, 1]
print y
# prints: [1, 2, 3, 1]  #  !!!! My list was modified

代わりにコピーする場合: ( http://docs.python.org/library/copy.htmlを参照)

import copy
class A:
  def foo(self, x = [] ):
    x = copy.copy(x)
    x.append(1)
    self.x = x

a = A()
a.foo()
print a.x
# prints: [1]
a.foo()
print a.x
# prints: [1]   # !!! Much better =)
y = [1,2,3]
a.foo(y)
print a.x
# prints: [1, 2, 3, 1]
print y
# prints: [1, 2, 3]  #  !!!! My list is how I made it
于 2010-01-17T05:59:39.827 に答える