2017-12-14 24 views
-1

イメージバッファ用のクラスを作成します。クラスは次のようになります。ctypes属性を持つPythonクラスには副作用があります

import ctypes 

class ImgBuf(): 
    def __init__(self, bufnr=ctypes.c_int(-1)): 
     self.bufnr = bufnr 

属性「bufnr」参照することにより、共有ライブラリに引き渡され、バッファ管理のために変更されます。私はこのクラスの複数のインスタンスを(複数のイメージバッファを管理するため)持っていると思います。小さな例

import imgBuf.ImgBuf 
buf1 = dicamsdk.ImgBuf() 
buf2 = dicamsdk.ImgBuf() 
sharedDLL.allocateBuffer(buf1) 
bufNr

の両方の場合において変更されています。インスタンスを独立させるにはどうすればいいですか?

+0

私はそれを実行しようとすると、私は 'TypeError例外を取得::' ctypes.c_int(bufnr)に整数が必要です(GOTタイプc_intのを) 'あなたは、関数が呼び出された新しいオブジェクトを毎回作成する必要があります'呼び出し。これはあなたが実際に走ったものだと確信していますか? – user2357112

+0

実際には、コードが減少したためにタイプがありました。それを修正しました。ありがとう。 – smiddy84

答えて

-1

は、次のコードは切り取ら参照:

from imgBuf import ImgBuf 
buf1 = ImgBuf() 
buf2 = ImgBuf() 
print('id(buf1) == id(buf2): ', id(buf1) == id(buf2)) 
print('id(buf1.bufnr) == id(buf2.bufnr): ', id(buf1.bufnr) == id(buf2.bufnr)) 

出力はPythonが正しくクラスオブジェクトの2つのインスタンスを作成するにもかかわらず、ctypesの値が同じIDを持つ

id(buf1) == id(buf2): False 
id(buf1.bufnr) == id(buf2.bufnr): True 

です。通常、pythonがストレージを管理するので、これは問題ではありません。しかし、これは使用中の共用ライブラリーには当てはまりません。

デフォルト値は、独立したインスタンスを確実にするためにコピーされています。クラスは次のようになります。

import ctypes 
from copy import copy 

class ImgBuf(): 
    def __init__(self, bufnr=ctypes.c_int(-1)): 
     self.bufnr = copy(ctypes.c_int(bufnr)) 

オブジェクトは独立している必要があります(実行コードはもう一度切り詰めます)。

1

bufnrのようなkwargのデフォルト値は、defステートメントが読み込まれるときにロード時に1回だけ評価されます。この場合、c_intが一度作成され、明示的にbufnrが指定されていないすべてのImgBufインスタンスに対して同じインスタンスが使用されます。

これを回避するには、デフォルトでNoneを使用してから、is Noneをチェックし、必要に応じて関数の本文内にデフォルト値をインスタンス化します。これにより、毎回新しいインスタンスが作成されます。

同じことが、デフォルト値として使用されるその他の変更可能なオブジェクト(リストやdictsなど)にも適用されます。 this linkを参照してください。

2

ctypes.c_intは、listのように可変であり、デフォルトの引数として使用するべきではありません。よくある間違いです。

class ImgBuf(): 
    def __init__(self, bufnr=None): 
     if bufnr is None: 
      bufnr = ctypes.c_int(-1) 
     self.bufnr =ctypes.c_int(bufnr)