2015-05-28 13 views
8

Unicode dizeleri adlandırılmış bir ad için ad olarak atamada sorun yaşıyorum.adında unicode dizesiyle adlandırılmış ad alanı

a = collections.namedtuple("test", "value") 

ve bu değildir: Bu işler

b = collections.namedtuple("βαδιζόντων", "value") 

Ben

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python3.4/collections/__init__.py", line 370, in namedtuple 
     result = namespace[typename] 
KeyError: 'βαδιζόντων' 

Neden vaka olduğunu hatası alıyorum? Dokümantasyonda "Python 3 tanımlayıcılarda Unicode karakterlerini de destekliyor" ve anahtar geçerli unicode mu?

+1

Farkettiğim bir şey var: Eğer '' ó'' dışı bırakırsam iyi çalışır. Bana bir böcek gibi görünüyor. – pmos

+0

İlginç - Kendimi test etmeliydim. ó unicode "Yunan Uzatılmış" bloğundan gelen tek karakter, bu yüzden alakalı olabilir. Ancak belgelerin söylediği şeyle aynı fikirde değil. – Thomas

+0

Daha yakından inceleme yapıldığında, bir sebepten dolayı, '' ó''' UTF-8 kodlu kaynak dosyada '' '\ xe1 \ xbd \ xb9''' değil,' ''\' ye dönüşür xcf \ x8c ', 'namedtuple'' tarafından oluşturulan kodda kendi sınıfını oluşturur. Bu kesinlikle bir böcek gibi görünüyor. – pmos

cevap

4

sorun harfi (OXIA U + 1F79 Yunan küçük harf OMiCRON) ile özel bir. Bu bir "uyumluluk karakteridir": Unicode bunun yerine ό kullanmayı tercih eder (tonlarla U + 03CC Yunan küçük harf omicron). U + 1F79, Unicode'da sadece oksi ve tonos arasında ayrım yapan eski karakter kümelerine, daha sonra yanlış olduğu ortaya çıkan bir ayırıma geçmek için var.

Eğer bir tanımlayıcı uyumluluk karakterleri kullandığınızda, Python'un kaynak kodu çözümleyici otomatik NFKC oluşturmak üzere onları normale, bu nedenle sınıf adının U + 03CC ile biter.

Maalesef collections.namedtuple bundan haberi yoktur. yeni sınıf örneğini oluşturur yolu bir dizede Python kodunun bir demet haline verilen ad ekleyerek, daha sonra exec UTING o (iğrenç, değil mi?) ve onun adını kullanarak Dict çıkan halk sınıfından ayıklanması ... Orijinal adı, Python normalleştirilmiş sürümü aslında derlenmiş değil, bu yüzden başarısız olur.

Bu, dosyalamaya değer olabilecek collections numaralı hatadır, ancak şimdilik U + 03CC ό kanonik karakterini kullanmalısınız.

+0

Arrg, şimdi anlıyorum! Yunanca aksanlı harfler için bu uyumluluk karakterlerinden birkaç kez ısırıldım. En azından bu sorun etrafında çalışmamı sağlıyor. Açıklamanız için teşekkürler! – Thomas

+0

Kaynak kod referansı yararlı olacaktır https://hg.python.org/cpython/file/661cdbd617b8/Lib/collections/__init__.py#l332 – Kasramvd

2

ó U +, 1F79 olup bu ɢʀᴇᴇᴋ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴏᴍɪᴄʀᴏɴ ᴡɪᴛʜ ᴏxɪᴀ. Python tanımlayıcıları NFKC olarak normalize edilir ve NFKC'de U + 1F79 U + 03CC ɢʀᴇᴇᴋ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴏᴍɪᴄʀᴏɴ ᴡɪᴛʜ becomess olur. U + 03CC yerine U + 1F79 ile aynı dizeyi kullanın eğer

İlginç işe yarıyor.

>>> b = collections.namedtuple("βαδιζ\u03CCντων", "value") 
>>> 

"Herhangi geçerli Python tanımlayıcı bir fieldname kullanılabilir" diye namedtuple iddiaları için dokümantasyon. Her iki dizge de yorumlayıcıda kolayca test edilebildiği gibi geçerli Python tanımlayıcılarıdır.

>>> βαδιζόντων = 0 
>>> βαδιζόντων = 0 
>>> 

Bu, kesinlikle uygulamada bir hatadır. Ben namedtuple uygulanmasında bu bite onu takip:

Ben, class_definition şablonu exec'ing bir Python tanımlayıcı kalarak namespace sözlükte sol typename, hiçbir nedenle NFKC şeklinde olacak ve tahmin
namespace = dict(__name__='namedtuple_%s' % typename) 
exec(class_definition, namespace) 
result = namespace[typename] # here! 

almak için kullanılan typename değişkeninin gerçek değeriyle daha uzun eşleşir. Sadece typename'un normalize edilmesinin bu sorunu çözmesi gerektiğine inanıyorum, ama ben bunu test etmedim.

+0

Teşekkür ederim, girdimi dezenfekte edeceğim ve en iyisini umuyorum! – Thomas

1

zaten var Althoug kabul edilen bir cevap beni soruna

# coding: utf-8 
import collections 
import unicodedata 


def namedtuple_(typename, field_names, verbose=False, rename=False): 
    ''' just like collections.namedtuple(), but does unicode nomalization 
     on names 
    ''' 

    if isinstance(field_names, str): 
     field_names = field_names.replace(',', ' ').split() 
    field_names = [ 
     unicodedata.normalize('NFKC', name) for name in field_names] 
    typename = unicodedata.normalize('NFKC', typename) 

    return collections.namedtuple(
     typename, field_names, verbose=False, rename=False) 


βαδιζόντων = namedtuple_('βαδιζόντων', 'value') 

a = βαδιζόντων(1) 

print(a) 
# βαδιζόντων(value=1) 
print(a.value == 1) 
# True 

Ne yapar bir

Fix vermesini sağlar? Bu namedtuple_() uygulamaları kullanan

mümkün uyumlu isimlere sahip hale collections.namedtuple() teslim etmek önce isimleri normalize.

Bu, @R üzerinde ayrıntılı bir ayrıntıdır. Martinho Fernandes'in isimleri önceden nomalize etme fikri.

+0

Teşekkür ederim, bu çok yararlı! Benim özel kullanım durumumun çözülmeyeceğinden şüpheleniyorum (bu, bir metin dosyasından bir sözcük listesi çıkarmayı ve onu bilinen sözcüklerin bir listesiyle karşılaştırmayı içerir), ama sahip olmak çok güzel! – Thomas

+0

yardımcı olabilir, nasıl/neden karşılaştırdığınıza bağlı olarak ... NFKC formundan regexp ile birleştiren stripleri bir araya getirebilir ve tüm nomalizasyonu bir alt() ile tamamlayabilirsiniz. – knitti