Python C-benzeri yapılar

oy
304

elverişli Python bir C-benzeri yapıyı tanımlamak için bir yol var mı? Ben böyle şeyler yazma yoruldum:

class MyStruct():
    def __init__(self, field1, field2, field3):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3
Oluştur 30/08/2008 saat 13:33
kaynak kullanıcı
Diğer dillerde...                            


23 cevaplar

oy
52

Nasıl bir sözlüğe hakkında?

Böyle bir şey:

myStruct = {'field1': 'some val', 'field2': 'some val'}

Sonra değerlerini işlemek için kullanabilir:

print myStruct['field1']
myStruct['field2'] = 'some other values'

Ve değerler dizeleri olmak gerekmez. Onlar hemen hemen herhangi bir başka nesne olabilir.

Cevap 30/08/2008 saat 13:35
kaynak kullanıcı

oy
91

Eğer C (örneğin x, y koordinatlarına veya RGB renk gibi bir şey) içinde bir yapı kullanmak istiyorsunuz bir çok şey için bir demet kullanabilirsiniz.

Diğer her şey için size sözlüğü ya da benzeri bir yardımcı sınıf kullanabilirsiniz bu bir :

>>> class Bunch:
...     def __init__(self, **kwds):
...         self.__dict__.update(kwds)
...
>>> mystruct = Bunch(field1=value1, field2=value2)

Ben "kesin" tartışması olduğunu düşünüyorum burada Python Cookbook yayınlanan sürümde.

Cevap 30/08/2008 saat 13:38
kaynak kullanıcı

oy
289

Bir kullan adında tuple eklendi, koleksiyonları modülü Python 2.6 standart kütüphanede. Raymond Hettinger en kullanmak da mümkündür adlı tanımlama grubu Python 2.4 desteklemek için gerekirse tarifi.

Bu sizin temel örneğin güzel, ama aynı zamanda daha sonra hem aday olabileceğini uç örnekleri bir demet kapsar. Kişisel fragmanı yukarıdaki gibi yazılabilir olacaktır:

from collections import namedtuple
MyStruct = namedtuple("MyStruct", "field1 field2 field3")

Yeni oluşturulan türü bu gibi kullanılabilir:

m = MyStruct("foo", "bar", "baz")

Ayrıca isimli değişkenler kullanabilirsiniz:

m = MyStruct(field1="foo", field2="bar", field3="baz")
Cevap 30/08/2008 saat 14:18
kaynak kullanıcı

oy
23

dF: bu gerçekten harika ... Ben dict kullanarak sınıftaki alanlara erişmek olabileceğini bilmiyordum.

Mark: Ben bir sözlük olarak "ağır" olarak bir demet başka bir şey istediğinizde bu hassas olan olsaydı durumlar.

Bir sınıfın alanları, yöntemleri ve tüm özellikleri (en azından CPython olarak) dicts kullanılarak dahili olarak depolandığı için bir sözlük kullanarak bir sınıfın alanlarını erişebilirsiniz.

... hangisi ikinci yorumun götürür. Python dicts "ağır" olduğunu inanan son derece olmayan pythonistic kavramdır. Ve böyle bir yorum okuma benim Python Zen öldürür. Bu iyi değil.

şey, sen basit bir sözlük kullanarak daha fazla yükü ekliyorsanız, bu nedenle - Sen aslında bir sözlüğe çevresinde oldukça karmaşık sarıcı oluştururken bir sınıfı bildirirken, bkz. Bu arada, her durumda anlamsız olan bir havai. Performans kritik uygulamalar üzerinde çalışıyorsanız, C veya bir şey kullanın.

Cevap 30/08/2008 saat 14:20
kaynak kullanıcı

oy
14

Ayrıca konuma göre örnek değişkenlerine init parametreleri geçebilir

# Abstract struct class       
class Struct:
    def __init__ (self, *argv, **argd):
        if len(argd):
            # Update by dictionary
            self.__dict__.update (argd)
        else:
            # Update by position
            attrs = filter (lambda x: x[0:2] != "__", dir(self))
            for n in range(len(argv)):
                setattr(self, attrs[n], argv[n])

# Specific class
class Point3dStruct (Struct):
    x = 0
    y = 0
    z = 0

pt1 = Point3dStruct()
pt1.x = 10

print pt1.x
print "-"*10

pt2 = Point3dStruct(5, 6)

print pt2.x, pt2.y
print "-"*10

pt3 = Point3dStruct (x=1, y=2, z=3)
print pt3.x, pt3.y, pt3.z
print "-"*10
Cevap 30/08/2008 saat 14:53
kaynak kullanıcı

oy
75

Belki kurucular olmadan Yapılar arıyoruz:

class Sample:
  name = ''
  average = 0.0
  values = None # list cannot be initialized here!


s1 = Sample()
s1.name = "sample 1"
s1.values = []
s1.values.append(1)
s1.values.append(2)
s1.values.append(3)

s2 = Sample()
s2.name = "sample 2"
s2.values = []
s2.values.append(4)

for v in s1.values:   # prints 1,2,3 --> OK.
  print v
print "***"
for v in s2.values:   # prints 4 --> OK.
  print v
Cevap 21/09/2010 saat 14:15
kaynak kullanıcı

oy
9

(Ben bir "aynı zamanda bir sözlük gibi davranır anlık veri nesnesi" her ihtiyacın yok ! C yapılar düşünün), bu sevimli kesmek düşünüyorum:

class Map(dict):
    def __init__(self, **kwargs):
        super(Map, self).__init__(**kwargs)
        self.__dict__ = self

Şimdi sadece söyleyebiliriz:

struct = Map(field1='foo', field2='bar', field3=42)

self.assertEquals('bar', struct.field2)
self.assertEquals(42, struct['field3'])

Eğer, ve namedtuples anlaşılmaz olduğunda bir "DEĞİL sınıf var veri torbasını" gerektiğinde zamanlar için mükemmel kullanışlı ...

Cevap 13/09/2013 saat 16:40
kaynak kullanıcı

oy
6

Yolu aşağıdaki Python, C-Stil yapı erişin.

class cstruct:
    var_i = 0
    var_f = 0.0
    var_str = ""

Sadece cstruct nesne kullanmak isterseniz

obj = cstruct()
obj.var_i = 50
obj.var_f = 50.00
obj.var_str = "fifty"
print "cstruct: obj i=%d f=%f s=%s" %(obj.var_i, obj.var_f, obj.var_str)

Eğer cstruct nesneler dizisi oluşturmak istiyorsanız

obj_array = [cstruct() for i in range(10)]
obj_array[0].var_i = 10
obj_array[0].var_f = 10.00
obj_array[0].var_str = "ten"

#go ahead and fill rest of array instaces of struct

#print all the value
for i in range(10):
    print "cstruct: obj_array i=%d f=%f s=%s" %(obj_array[i].var_i, obj_array[i].var_f, obj_array[i].var_str)

Not: Bunun yerine 'cstruct' isminin, var_i, var_f, var_str yerine struct adını kullanmak lütfen, sizin yapının üyesi değişken tanımlamak ediniz.

Cevap 09/11/2014 saat 05:37
kaynak kullanıcı

oy
3

Bu biraz geç olabilir ama ben (çok altında dekoratör versiyonu) Python Meta Sınıfları kullanarak bir çözüm oldu.

Ne zaman __init__çalışma zamanı sırasında denir, bu argümanlar ve bunların değerinin her alır ve sınıfınıza örnek değişkenler olarak atar. El her değer atamak zorunda kalmadan bir yapı benzeri sınıfını yapabilir Bu şekilde.

Benim örnek, takip etmek daha kolaydır böylece kontrol hiçbir hata var.

class MyStruct(type):
    def __call__(cls, *args, **kwargs):
        names = cls.__init__.func_code.co_varnames[1:]

        self = type.__call__(cls, *args, **kwargs)

        for name, value in zip(names, args):
            setattr(self , name, value)

        for name, value in kwargs.iteritems():
            setattr(self , name, value)
        return self 

İşte hareket bulunmaktadır.

>>> class MyClass(object):
    __metaclass__ = MyStruct
    def __init__(self, a, b, c):
        pass


>>> my_instance = MyClass(1, 2, 3)
>>> my_instance.a
1
>>> 

Ben reddit'te yayınlanmıştır ve / u / Matchu temizleyici bir dekoratör versiyonunu yayınladı. Eğer Metaclass sürümünü genişletmek istediğiniz sürece bunu kullanmak öneririm.

>>> def init_all_args(fn):
    @wraps(fn)
    def wrapped_init(self, *args, **kwargs):
        names = fn.func_code.co_varnames[1:]

        for name, value in zip(names, args):
            setattr(self, name, value)

        for name, value in kwargs.iteritems():
            setattr(self, name, value)

    return wrapped_init

>>> class Test(object):
    @init_all_args
    def __init__(self, a, b):
        pass


>>> a = Test(1, 2)
>>> a.a
1
>>> 
Cevap 23/03/2015 saat 12:32
kaynak kullanıcı

oy
12

Standart kütüphanede mevcuttur C yapısını alt sınıf. Ctypes modülü sağlar Yapısı sınıfı . Dokümanlardan örnek:

>>> from ctypes import *
>>> class POINT(Structure):
...     _fields_ = [("x", c_int),
...                 ("y", c_int)]
...
>>> point = POINT(10, 20)
>>> print point.x, point.y
10 20
>>> point = POINT(y=5)
>>> print point.x, point.y
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: too many initializers
>>>
>>> class RECT(Structure):
...     _fields_ = [("upperleft", POINT),
...                 ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print rc.upperleft.x, rc.upperleft.y
0 5
>>> print rc.lowerright.x, rc.lowerright.y
0 0
>>>
Cevap 25/06/2015 saat 22:50
kaynak kullanıcı

oy
4

Sana verilen bağımsız değişken veya herhangi varsayılan hepsi örneğine atanmış böylece bunu yapmak için herhangi bir yöntem üzerinde kullanabileceğiniz bir dekoratör yazdı.

def argumentsToAttributes(method):
    argumentNames = method.func_code.co_varnames[1:]

    # Generate a dictionary of default values:
    defaultsDict = {}
    defaults = method.func_defaults if method.func_defaults else ()
    for i, default in enumerate(defaults, start = len(argumentNames) - len(defaults)):
        defaultsDict[argumentNames[i]] = default

    def newMethod(self, *args, **kwargs):
        # Use the positional arguments.
        for name, value in zip(argumentNames, args):
            setattr(self, name, value)

        # Add the key word arguments. If anything is missing, use the default.
        for name in argumentNames[len(args):]:
            setattr(self, name, kwargs.get(name, defaultsDict[name]))

        # Run whatever else the method needs to do.
        method(self, *args, **kwargs)

    return newMethod

Hızlı bir gösteri. Bir konumsal argüman kullandığını unutmayın a, varsayılan değeri kullanmak bve adlandırılmış argüman c. Sonra 3 referanslamaya yazdırmak selfyöntem girilmeden önce düzgün atandım göstermek için.

class A(object):
    @argumentsToAttributes
    def __init__(self, a, b = 'Invisible', c = 'Hello'):
        print(self.a)
        print(self.b)
        print(self.c)

A('Why', c = 'Nothing')

Benim dekoratör sadece, herhangi bir yöntemle çalışması gerektiğini unutmayın __init__.

Cevap 08/09/2015 saat 01:38
kaynak kullanıcı

oy
1

Burada bu cevabı görmüyorum, bu yüzden şu anda Python öğreniyorken beri bunu ekleriz anlamaya ve sadece keşfetti. Python öğretici (bu durumda Python 2) Aşağıdaki basit ve etkili örnek verir:

class Employee:
    pass

john = Employee()  # Create an empty employee record

# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000

Yani boş bir sınıf nesne daha sonra örneği, oluşturulur olduğunu ve alanların dinamik olarak eklenir.

Bu kadar taraflı onun gerçekten basittir. Olumsuz özellikle kendinden belgeleyen (amaçlanan üyeleri yerde sınıf "tanımına" listelenmeyen) değil, ve erişildiğinde tanımsız alanların sorunlara neden olabilir. Bu iki sorun çözülebilir:

class Employee:
    def __init__ (self):
        self.name = None # or whatever
        self.dept = None
        self.salary = None

Şimdi bir bakışta en az bir program bekliyor olacak alanları görebilirsiniz.

Hem yazım hataları yatkındır john.slarly = 1000başarılı olacaktır. Yine de çalışır.

Cevap 08/11/2016 saat 12:06
kaynak kullanıcı

oy
0

Ben Python yapı sözlüğü bu şartı için uygun olduğunu düşünüyorum.

d = dict{}
d[field1] = field1
d[field2] = field2
d[field2] = field3
Cevap 08/07/2017 saat 18:17
kaynak kullanıcı

oy
35

Güncelleme : Veri Sınıflar

Tanıtılmasıyla Veri Sınıflar içinde Python 3.7 çok yakın olsun.

Aşağıdaki örnek, benzer NamedTuple Aşağıdaki örnekte, ama elde edilen nesne kesilebilir ve bu varsayılan değerler sağlar.

@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0

p = Point(1.5, 2.5)
print(p)   # produces "Point(x=1.5, y=2.5, z=0.0)"

Bu yeni ile güzel oynar yazarak daha spesifik tip ek açıklamaları kullanmak istediğiniz durumda modül.

Bunun için umutsuzca bekliyordum! Eğer, bana sorarsanız Veri Sınıfları ve yeni NamedTuple ile kombine beyanı, yazarak modülü bir meleksin!

Geliştirilmiş NamedTuple declartaion

Yana Python 3.6 o sürece değişmezlik ile yaşamak gibi, (IMHO) oldukça basit ve güzel oldu.

NamedTuples ilan etme yeni bir yol için izin veren tanıtıldı tip ek açıklamalar yanı:

from typing import NamedTuple

class MyStruct(NamedTuple):
    my_string: str
    my_int: int
    my_list: list
    my_dict: dict
    my_foo: Foo

Bu şekilde kullanın:

my_item = MyStruct(
    my_string='foo',
    my_int=0,
    my_list=['bar'],
    my_dict={'baz': 'qux'},
    my_foo=Foo('bar')
)

Ya da bu gibi gerçekten istiyorsan:

my_item = MyStruct('foo', 0, ['bar'], {'baz': 'qux'}, Foo('bar'))
Cevap 31/07/2017 saat 21:54
kaynak kullanıcı

oy
5

Burada bazı yanıtlar kitlesel özenlidir. Bulduğum basit seçenek (: dan http://norvig.com/python-iaq.html ):

class Struct:
    "A structure that can have any fields defined."
    def __init__(self, **entries): self.__dict__.update(entries)

başlatılması Açıklama:

>>> options = Struct(answer=42, linelen=80, font='courier')
>>> options.answer
42

daha ekleyerek:

>>> options.cat = "dog"
>>> options.cat
dog

düzenleme: Üzgünüm daha da aşağı zaten bu örneği görmedik.

Cevap 04/08/2017 saat 23:39
kaynak kullanıcı

oy
0

https://stackoverflow.com/a/32448434/159695 Python3 çalışmaz.

https://stackoverflow.com/a/35993/159695 Python3 çalışır.

Ve bunun varsayılan değerler eklemek uzanır.

class myStruct:
    def __init__(self, **kwds):
        self.x=0
        self.__dict__.update(kwds) # Must be last to accept assigned member variable.
    def __repr__(self):
        args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()]
        return '%s(%s)' % ( self.__class__.__qualname__, ', '.join(args) )

a=myStruct()
b=myStruct(x=3,y='test')
c=myStruct(x='str')

>>> a
myStruct(x=0)
>>> b
myStruct(x=3, y='test')
>>> c
myStruct(x='str')
Cevap 30/10/2017 saat 11:40
kaynak kullanıcı

oy
1

Şahsen ben de bu varyant gibi. Bu uzanır DF cevabı @ .

class struct:
    def __init__(self, *sequential, **named):
        fields = dict(zip(sequential, [None]*len(sequential)), **named)
        self.__dict__.update(fields)
    def __repr__(self):
        return str(self.__dict__)

Bu başlatma (yani harmanlanabilir) iki modları vardır:

# Struct with field1, field2, field3 that are initialized to None.
mystruct1 = struct("field1", "field2", "field3") 
# Struct with field1, field2, field3 that are initialized according to arguments.
mystruct2 = struct(field1=1, field2=2, field3=3)

Ayrıca, güzel yazdırır:

print(mystruct2)
# Prints: {'field3': 3, 'field1': 1, 'field2': 2}
Cevap 06/11/2017 saat 13:38
kaynak kullanıcı

oy
1

Bir yapı için aşağıdaki çözüm namedtuple uygulanması ve önceki bazı yanıtlar esinlenmiştir. Ancak namedtuple aksine o en değerlerinde, değişken olmakla birlikte, normal bir sınıf veya dict değildir adları / özelliklerinde değişmez c tarzı yapı gibi.

_class_template = """\
class {typename}:
def __init__(self, *args, **kwargs):
    fields = {field_names!r}

    for x in fields:
        setattr(self, x, None)            

    for name, value in zip(fields, args):
        setattr(self, name, value)

    for name, value in kwargs.items():
        setattr(self, name, value)            

def __repr__(self):
    return str(vars(self))

def __setattr__(self, name, value):
    if name not in {field_names!r}:
        raise KeyError("invalid name: %s" % name)
    object.__setattr__(self, name, value)            
"""

def struct(typename, field_names):

    class_definition = _class_template.format(
        typename = typename,
        field_names = field_names)

    namespace = dict(__name__='struct_%s' % typename)
    exec(class_definition, namespace)
    result = namespace[typename]
    result._source = class_definition

    return result

Kullanımı:

Person = struct('Person', ['firstname','lastname'])
generic = Person()
michael = Person('Michael')
jones = Person(lastname = 'Jones')


In [168]: michael.middlename = 'ben'
Traceback (most recent call last):

  File "<ipython-input-168-b31c393c0d67>", line 1, in <module>
michael.middlename = 'ben'

  File "<string>", line 19, in __setattr__

KeyError: 'invalid name: middlename'
Cevap 29/03/2018 saat 15:25
kaynak kullanıcı

oy
1

Ben de kullanan bir çözüm eklemek istiyorum yuvaları :

class Point:
    __slots__ = ["x", "y"]
    def __init__(self, x, y):
        self.x = x
        self.y = y

Kesinlikle yuvaları belgelerine kontrol ama yuvaları hızlı bir açıklama bunun söylemenin Python yoludur şudur: "Eğer sınıfta bir kez herhangi bir yeni özellikler eklemek etmeyeceğini taahhüt şekilde sınıfa bu özellikleri ve sadece bu özellikleri kilitleyebilir ise (evet aşağıdaki örneğe bakın, bir sınıf örneğine yeni özellik ekleyebilirsiniz) o zaman ben uzakta bir sınıf örneğine özellikler eklemenin sağlayan geniş bellek tahsisi ile yapmak ve bunlar için sadece gerekenler kullanacak örneği yarıklı nitelikler".

(Bu şekilde yuva kullanmayan) sınıfı örneği özelliklerini ekleme örneği:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p1 = Point(3,5)
p1.z = 8
print(p1.z)

Çıktı: 8

yuvaları kullanıldığı yerlerde sınıf örneğine özelliklerini eklemeye çalışırken örneği:

class Point:
    __slots__ = ["x", "y"]
    def __init__(self, x, y):
        self.x = x
        self.y = y

p1 = Point(3,5)
p1.z = 8

Çıkış: AttributeError: 'nokta' nesnesi niteliği 'z' var

Bu yapabilirsiniz etkili bir yapı olarak çalışır ve bir sınıf daha az bellek kullanır (bir yapı gibi olur, ben tam olarak ne kadar araştırılmış değil rağmen). Nesnenin örneklerinin büyük miktarda oluşturacağınız ve özellikler eklemek gerek yoksa yuvaları kullanılması önerilir. bir veri kümesi tanımlamak için çok puan örneğini olasıdır gibi bir nokta amacı, bu iyi bir örnektir.

Cevap 12/04/2018 saat 05:17
kaynak kullanıcı

oy
1

Bu amaçla tam bir piton paketi yok. bkz cstruct2py

cstruct2pyC kodundan piton sınıfları oluşturmak ve verileri paketi ve açmak için bunları kullanmak için saf piton kütüphanesidir. kütüphanesi C headres (yapılar, sendikalar, çeteleler ve diziler beyanları) ayrıştırması ve piton onları taklit edebilir. oluşturulan pythonic sınıflar ayrıştırmak ve verileri paketi olabilir.

Örneğin:

typedef struct {
  int x;
  int y;
} Point;

after generating pythonic class...
p = Point(x=0x1234, y=0x5678)
p.packed == "\x34\x12\x00\x00\x78\x56\x00\x00"

Nasıl kullanılır

Öncelikle pythonic yapılar oluşturmak gerekir:

import cstruct2py
parser = cstruct2py.c2py.Parser()
parser.parse_file('examples/example.h')

Şimdi C kodundan tüm adları alabilirsiniz:

parser.update_globals(globals())

Biz de doğrudan yapabiliriz:

A = parser.parse_string('struct A { int x; int y;};')

türleri kullanarak ve C kodundan tanımlar

a = A()
a.x = 45
print a
buf = a.packed
b = A(buf)
print b
c = A('aaaa11112222', 2)
print c
print repr(c)

çıkış olacaktır:

{'x':0x2d, 'y':0x0}
{'x':0x2d, 'y':0x0}
{'x':0x31316161, 'y':0x32323131}
A('aa111122', x=0x31316161, y=0x32323131)

Klon

Klon için cstruct2pyçalışma:

git clone https://github.com/st0ky/cstruct2py.git --recursive
Cevap 11/12/2018 saat 07:34
kaynak kullanıcı

oy
0

Eğer @dataclass için 3.7 olması ve değişebilirlik gerekmiyorsa, aşağıdaki kodu sizin için işe yarayabilecek. Oldukça kendi kendini belgeleyen ve IDE dostu (otomatik tamamlama), iki kez yazı işleri engeller kolayca uzayabilen ve tüm örnek değişkenleri tam olarak başlatılmış olduğunu test etmek çok basittir var:

class Params():
    def __init__(self):
        self.var1 : int = None
        self.var2 : str = None

    def are_all_defined(self):
        for key, value in self.__dict__.items():
            assert (value is not None), "instance variable {} is still None".format(key)
        return True


params = Params()
params.var1 = 2
params.var2 = 'hello'
assert(params.are_all_defined)
Cevap 28/01/2019 saat 09:27
kaynak kullanıcı

oy
0

İşte verileri tutmak için (asla örneği) bir sınıf kullanan bir çözümdür. Ben bu şekilde çok az yazarak içerir ve herhangi bir ek paket gerektirmediği gibi vs

class myStruct:
    field1 = "one"
    field2 = "2"

Gerektiğinde, daha sonra daha fazla alan ekleyebilirsiniz:

myStruct.field3 = 3

değerlerini elde etmek için, alanlar her zamanki gibi erişilir:

>>> myStruct.field1
'one'
Cevap 09/04/2019 saat 10:10
kaynak kullanıcı

oy
0

Burada hızlı ve kirli hile:

>>> ms = Warning()
>>> ms.foo = 123
>>> ms.bar = 'akafrit'

Nasıl Çalışır yapar? Bu sadece yerleşik sınıf yeniden kullanmak Warning(türetilmiş Exception) ve tanımladığınız sınıfını kendi olarak kullanmak.

İyi noktaları "Uyarı" Kısa bir isim olduğunu içe ya da ilk şey tanımlamak gerekmez, ve aynı zamanda senin küçük bir komut daha başka yerde kullanılmamalıdır kirli bir şey yapıyorsun net yapar.

Bu arada, ben gibi daha basit bir şey bulmaya çalıştılar ms = object()ama (bu son exemple çalışmıyor) olamazdı. Eğer bir tane varsa, ben ilgileniyorum.

Cevap 26/09/2019 saat 15:56
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more