c# this als IronPython Variante

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
proofy
User
Beiträge: 32
Registriert: Montag 21. März 2011, 12:47

Moin Moin,

mal was zum knobeln ;)

aus der Dokumentation für eine Silverlight GUI Komponente (http://www.viblend.com/products/net/sil ... agrid.aspx) habe ich folgendes C# Beispiel:

Code: Alles auswählen

public partial class DemoPage : UserControl
{
    public DemoPage()
    {
        InitializeComponent();

        PopulateGridContent();
    }

    public class Person
    {
        public Person(string FirstName, string LastName)
        {
            this.FirstName = FirstName;
            this.LastName = LastName;
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    private void PopulateGridContent()
    {
        List<Person> list = new List<Person>();
        for (int i = 0; i < 10; i++)
            list.Add(new Person(
        "First Name " + i, 
        "Last Name " + i));

        dataGrid.ItemsSource = list;
    }
}

Wie könnte man dies als (Iron)Python Code schreiben?

Vielen Dank im Voraus
Sven
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Was gibt es da groß zu knobeln? Ich weiß nicht ob/wie IronPython partielle Klassen unterstützt, aber unter der Annahme, die Syntax lässt sich 1:1 umsetzen, müsste es so oder so ähnlich sein:

Code: Alles auswählen

@partial
class DemoPage(UserControl):
    def __init__(self):
        self.InitializeComponent()
        self.PopulateGridContent()
    
    def PopulateGridContent(self):
        self.dataGrid.ItemsSource = [Person("FN %d" % i, "LN %d" % i) for i in range(10)]

class Person:
    def __init__(self, fn, ln):
        self.fn, self.ln = fn, ln
Ich hatte keinen Bock FirstName und LastName auszuschreiben...

Stefan
Zuletzt geändert von sma am Montag 21. März 2011, 14:28, insgesamt 1-mal geändert.
BlackJack

@proofy: Also in reinem Python-Quelltext würde das wohl so aussehen:

Code: Alles auswählen

class Person(object):
    def __init__(self, FirstName, LastName):
        self.FirstName = FirstName
        self.LastName = LastName


class DemoPage(UserControl):
    def __init__(self):
        self.InitializeComponent()
        self._PopulateGridContent()
    
    def _PopulateGridContent(self):
        self.dataGrid.ItemsSource = [
            Person('First Name %d' % i, 'Last Name %d' % i) for i in xrange(10)
        ]
Das Problem ist ja aber wohl, dass `UserControl` ein .NET-Typ ist, die Personen-Liste eigentlich vom .NET-Typ `List<Person>` sein müsste, wobei die Python-Klasse `Person` auch irgendwie als .NET-Typ bekannt gemacht werden müsste. Also müsstest Du heraus finden wie man in IronPython von .NET-Typen ableitet und ob und wie man Python-Klassen irgendwie dem statischen Typsystem von .NET bekannt machen kann.
proofy
User
Beiträge: 32
Registriert: Montag 21. März 2011, 12:47

ach, so was blödes, verkehrtes Copy & Pase:
Das Beispiel sieht so aus:

Code: Alles auswählen

public class Person : INotifyPropertyChanged
{    
    public Person()
    {
    }

    private Dictionary<string, object> data = new Dictionary<string, object>();

    public object this[string key]
    {

        get
        {
            if (!data.ContainsKey(key))
            {
                data[key] = null;
            }

            return data[key];
        }

        set
        {
            data[key] = value;

            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(""));
            }
        }

    }

    public IEnumerable<string> Keys
    {
        get
        {
            return data.Keys;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
Genau dieses Verfahren wäre eine Umgehung der statischen Typen, dafür müsste man das Interface IEnumerable implementieren.
BlackJack

Reines Python:

Code: Alles auswählen

class Person(INotifyPropertyChanged):
    def __init__(self):
        self._data = dict()
        self.PropertyChanged = None
    
    def __getitem__(self, key):
        return self._data.setdefault(key, None)
    
    def __setitem__(self, key, value):
        self._data[key] = value
        if self.PropertyChanged:
            self.PropertyChanged(self, PropertyChangedEventArgs(''))
    
    @property
    def Keys(self):
        return self._data.keys()
Problem dürften aber auch hier wieder die Typen sein. Also wie sagt man .NET das `Person` ein .NET-Typ ist, der `INotifyPropertyChanged` implementiert. Wie sagt man .NET, dass `__getitem__`/`__setitem__` dem Indexoperator entspricht. Wie sagt man .NET das der Rückgabewert von `Keys` dem Typ `IEnumerable<string>` entspricht bzw. tut das eine Pythonliste überhaupt!? Da muss man vielleicht bei `Keys` einen konkreten .NET-Typ erstellen und die Schlüssel dort hinein kopieren.
proofy
User
Beiträge: 32
Registriert: Montag 21. März 2011, 12:47

Erstmal vielen Dank. __getitem__, __setitem__ kannte ich noch nicht und auch hier setdefault() so geschickt anzuwenden, fällt mir als python Anfänger noch schwer.

Die Magie mit den Typenzuweisungen könnte im einfachen Beispiel mit festen Typen so aussehen:

Code: Alles auswählen

import clr, clrtype


class Person(object):
    __metaclass__ = clrtype.ClrClass
    __clrnamespace = "MeineFirma.Beispiel"

    def __init__(self, inFirstName, inLastName):
        self._firstName = inFirstName
        self._lastName = inLastName

# nur getter
    @property
    @clrtype.accepts()
    @clrtype.returns(str)    
    def FirstName(self):
        return self._firstName

    @property
    @clrtype.accepts()
    @clrtype.returns(str)    
    def LastName(self):
        return self._lastName

Das funktioniert auch. IronPython konvertiert dabei automatisch http://ironpython.net/documentation/dot ... sion-rules .

Es ist aber scheinbar so wie du schon gesagt hast, dass komplexere Datentypen nicht funktionieren.
Dein Beispiel müsste ja so aussehen:

Code: Alles auswählen

class Person(object,INotifyPropertyChanged):
    __metaclass__ = clrtype.ClrClass
    __clrnamespace = "MeineFirma.Beispiel"

    def __init__(self):
        self._data = dict()
        self.PropertyChanged = None
 
    @clrtype.accepts(str)
    @clrtype.returns(object)      
    def __getitem__(self, key):
        return self._data.setdefault(key, None)

    @clrtype.accepts(str,object)
    @clrtype.returns()   
    def __setitem__(self, key, value):
        self._data[key] = value
        if self.PropertyChanged:
            self.PropertyChanged(self, PropertyChangedEventArgs(''))
   
    @property
    @clrtype.accepts()
    @clrtype.returns(IEnumerable)   
    def Keys(self):
        return self._data.keys()
Aber in der clrtype.py wird dann ein Fehler erzeugt: TypeError: expected Array[Type], got int
Antworten