2010-04-18 33 views
6

IronPython içinde .NET değer türleri kullanıldığında well known issue var. Bu son zamanlarda Python'u C# gömülü bir betik dili olarak kullanmaya çalışırken başım ağrıyordu. aşağıdaki gibi sorun özetlenebilir:C# IronPython'u yerleştirirken değer türleri nasıl kullanılır?

gibi bir C# yapı göz önüne alındığında:

struct Vector { 
    public float x; 
    public float y; 
} 

Ve sınıf C# gibi:

class Object { 
    public Vector position; 
} 

IronPython olur şu:

obj = Object() 
print obj.position.x # prints ‘0’ 
obj.position.x = 1 
print obj.position.x # still prints ‘0’ 

Makale belirtildiği gibi, bu, değer türlerinin çoğunlukla değişmez olduğu anlamına gelir. Ancak, yukarıda görüldüğü gibi uygulanan bir vektör kütüphanesi kullanmayı planladığım için bu bir problem. Değer türlerine dayanan mevcut kütüphanelerle çalışmak için herhangi bir geçici çözüm var mı? Kütüphaneyi değiştirmek son çare olurdu, ama bundan kaçınmayı tercih ederim. Aradığınızda

+0

Bu işe yarar mı? obj = Nesne() pos = Vektör() pos.x = 1 obj.position = pos –

+0

Evet, işler obj.position.x baskı. Uygun bir kurucu ile de 'obj.position = Vector (1,0) 'kullanabilirsiniz. Bu benim sorularımda anlattığım davranışlar hala kafa karıştırıcı olsa da bu kabul edilebilir olabilir ... – kloffy

cevap

4

sadece proxy kullanma, kütüphane düzenlenmesi için gerek yoktur.

struct Vector { 
    public float X; 
    public float Y; 
} 

class BetterVector { 
    public float X; 
    public float Y; 
    public Vector Optimized { get { return new Vector(X, Y); } } 
} 

class Object { 
    public BetterVector Position { get; set; } 
} 

Şimdi Python kodu, normal olarak alanları ayarlayabilirsiniz ve OpenGL veya XNA veya kullandığınız ne olursa olsun veri beslemek için ihtiyaç duyduğu zaman kodunuzu Optimized çağırabilir.

Optimized arayarak çok fazla iş gibi görünüyorsa bile örtük zorlama kullanabilirsiniz:

class BetterVector { 
    // ... 
    public static implicit operator Vector(BetterVector v) { 
     return v.Optimized; 
    } 
} 
+0

Bu özellikle oldukça gizlidir, özellikle örtük zorlamalarla. Bir grup vekil yazmak zorunda kalacaktı ama çok fazla çalışma olmamalı. Başka bir öneri olup olmadığını anlamak için soruyu biraz daha açık bırakacağım, ancak bu yaklaşımı beğendim. – kloffy

2

obj.position.x = 1

Ne elde ayarı, obj nesnesi size aslında bir kopyasını oluşturur pozisyon yapı, bir örneğini aldığını, bu yüzden X değeri yayılmaz.

Ne diyorsunuz, bu obj.position = Vector (1,0) yapmanız gereken şey. C# de benzer şeyler olur.


Düzen - etrafında mümkün çalışır.

Eğer yapıcı kurmak istemiyorsanız, ben bu işe inanıyoruz:

obj = Object() 
pos = obj.position; # gets the object 
pos.x = 1 
pos.y = 2 
obj.position = pos # I'm not sure if this line is necessary 
+0

Evet, hayır ve hayır. Değer türleri kavramını anlıyorum ve bunları IronPython'a çevirirken karşılaştıkları zorlukları görebiliyorum. Ancak, mevcut çözüm, C# içindeki (bağlantılı makalede belirtildiği gibi) davranıştan farklıdır ve Python'un çalışma biçimlerinden farklıdır (değer türlerine sahip değildir). Eğer IronPython bir "getattrref" işlevi gibi bir şeye sahip olsaydı, bu da kullanıcıların C# davranışını yeniden yaratmalarını mümkün kılıyordu. – kloffy

+0

Evet, C# farklıdır, ancak davranış benzerdir. Cevabımı güncelledim, bu biraz daha iyi çalışabilir – McKay

+0

Bu sözdizimsel benzer görünmesini kötü bir yol değil, ama C# ile aynı semantik almak için bir yol olup olmadığını merak ediyorum (yani bir Vektörün yeni kopyası). – kloffy

1

Ben yapılar güncellemek için bulduk tek yolu, herhangi bir kamu alanını belirtebilirsiniz gerçeği yararlanmak için struct oluştururken özellik. Sözdizimi Python'da adlandırılmış/isteğe bağlı parametrelere benziyor.

namespace StructExample 
{ 
    public struct MyStruct 
    { 
     public int x; 
     public int y { get; set; } 
    } 

    public class MyClass 
    { 
     public MyStruct a; 
    } 
} 

Biz böyle IronPython sınıfları kullanabilirsiniz: Python yeni bir yapı oluşturmak için 'ile' F # gibi bir söz dizimi olsaydı

>>> foo = MyClass() 
>>> print "%d:%d" % (foo.a.x, foo.a.y) 
0:0 
>>> foo.a.x = 1 # doesn't work! 
>>> print "%d:%d" % (foo.a.x, foo.a.y) 
0:0 
>>> foo.a = MyStruct(x=1,y=2) 
>>> print "%d:%d" % (foo.a.x, foo.a.y) 
1:2 

iyi olurdu, gelen alanları kopyalama eski olan. Maalesef bir yapıyı klonlarken tüm alanları belirtmek zorundayız.

+0

Kwargs yapıcısından bahsettiğiniz için teşekkürler, bu çok kullanışlı olabilir. – kloffy

-1

Böyle bir köşede sona erdiğini düşünün. python'da eşdeğer kod bu konuda olurdu (IronPython 2.6.1, .Net 4.0 üzerinde denedim):

>>> class a: 
... x = 0 
... y = 0 
... 
>>> class b: 
... Vector = a() 
... 
>>> c = b() 
>>> c.Vector.x = 1 
>>> print c.Vector.x 
1 

benim sözde kodu ve sizin arasında bir fark var Not - statik özelliği bir örneğini atanır sınıf, sadece tip tanımıyla kalmadı. Bir yan etki olarak, bir sınıfın gerçek bir örneği, b örneklendiğinde b.Vektör olarak başlatılır.

(sözde kod hala "bozuk" olduğunu - başlatma def init (öz) içine gitmek gerekir, ama bu farklı bir hikaye) yerine bırakmak,

örnek ahlaki "kamu Vektör pozisyonu "başlatılmamış," pozisyonunun "başlatılması" sınıf nesnesine.

+0

Yorumunuz için teşekkür ederiz. Ancak, bunun geçerli olduğunu sanmıyorum çünkü .NET değer türleri hakkında konuşuyordum. Sadece IronPython sınıflarını kullanarak aynı sorunla karşılaşmayacağınızın farkındayım. – kloffy

İlgili konular