SORU
4 Mayıs 2011, ÇARŞAMBA


Python bir karma sözlüğü

Önbelleğe alma amaçlı bir dict mevcut ALMAK argümanlar önbelleği bir anahtara ihtiyacım var.

Şu anda sha1(repr(sorted(my_dict.items()))) kullanıyorum (sha1() dahili hashlib kullanan bir kolaylık yöntemi) ama eğer daha iyi bir yolu varsa merak ediyorum.

CEVAP
3 Ocak 2012, Salı


EDİTBu cevap okumaya devam etmeden önce, lütfen Jack O'Connor bu çok daha kolay (ve daha hızlı) çözümü aşağıda da iç içe sözlükler karma için çalışan (O) bakın.

Cevap olarak kabul edilmiş olsa da, sorunun adı "python bir sözlük" olarak başlık ve cevap eksik. Karma. Soru cesedi ile ilgili olarak, cevap tamamlandı.)

İç İçe Geçmiş Sözlük

Bir arar bir sözlük karması için Yığın Taşması, bir yerinde adlı bu soruyu takılmaları, bir karma iç içe sözlükler çarpma girişiminde ise tatminsiz bırakabilir. Cevap yukarıda bu durumda işe yaramaz, ve özyinelemeli mekanizması bir çeşit karma almak için uygulamak zorunda kalırsınız.

İşte böyle bir düzenek:

import copy

def make_hash(o):

  """
  Makes a hash from a dictionary, list, tuple or set to any level, that contains
  only other hashable types (including any lists, tuples, sets, and
  dictionaries).
  """

  if isinstance(o, (set, tuple, list)):

    return tuple([make_hash(e) for e in o])    

  elif not isinstance(o, dict):

    return hash(o)

  new_o = copy.deepcopy(o)
  for k, v in new_o.items():
    new_o[k] = make_hash(v)

  return hash(tuple(frozenset(sorted(new_o.items()))))

Bonus: Karma Nesneler ve Sınıflar

Karma() işlevi çalışır sınıfları veya örneklerini karma büyük. Ancak, burada bir konuyla ilgili nesneleri olarak karma ile buldum:

class Foo(object): pass
foo = Foo()
print (hash(foo)) # 1209812346789
foo.a = 1
print (hash(foo)) # 1209812346789

Karma foo değiştirdim sonra bile aynıdır. Bu foo kimliğini karma aynıdır değişti, o yüzden alamadım çünkü. Eğer foo farklı akım tanımına bağlı olarak karma yapmak istiyorsanız, çözüm aslında değişen her ne ise karma. Bu durumda, __dict__ niteliği:

class Foo(object): pass
foo = Foo()
print (make_hash(foo.__dict__)) # 1209812346789
foo.a = 1
print (make_hash(foo.__dict__)) # -78956430974785

Sınıfın kendisi ile aynı şeyi yapmak istediğinizde ne yazık ki:

print (make_hash(Foo.__dict__)) # TypeError: unhashable type: 'dict_proxy'

____ Özellik dict sınıfı normal bir sözlük değildir

print (type(Foo.__dict__)) # type <'dict_proxy'>

Burada sınıfları uygun şekilde işleyen bir önceki benzer bir mekanizma

import copy

DictProxyType = type(object.__dict__)

def make_hash(o):

  """
  Makes a hash from a dictionary, list, tuple or set to any level, that 
  contains only other hashable types (including any lists, tuples, sets, and
  dictionaries). In the case where other kinds of objects (like classes) need 
  to be hashed, pass in a collection of object attributes that are pertinent. 
  For example, a class can be hashed in this fashion:

    make_hash([cls.__dict__, cls.__name__])

  A function can be hashed like so:

    make_hash([fn.__dict__, fn.__code__])
  """

  if type(o) == DictProxyType:
    o2 = {}
    for k, v in o.items():
      if not k.startswith("__"):
        o2[k] = v
    o = o2  

  if isinstance(o, (set, tuple, list)):

    return tuple([make_hash(e) for e in o])    

  elif not isinstance(o, dict):

    return hash(o)

  new_o = copy.deepcopy(o)
  for k, v in new_o.items():
    new_o[k] = make_hash(v)

  return hash(tuple(frozenset(sorted(new_o.items()))))

Bu ancak çok istediğiniz bir karma demet döndürmek için kullanabilirsiniz:

# -7666086133114527897
print (make_hash(func.__code__))

# (-7666086133114527897, 3527539)
print (make_hash([func.__code__, func.__dict__]))

# (-7666086133114527897, 3527539, -509551383349783210)
print (make_hash([func.__code__, func.__dict__, func.__name__]))

Python 3 varsayar.NOT: x. Make_hash sanıyorum, ancak önceki sürümleri test etmedi() çalışır,, 2.7.2 söylüyorlar. Bildiğim kadarıyla örnek çalışma yapma, benyapınbiliyorum

func.__code__ 

ile değiştirilmelidir

func.func_code

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dirkgently1

    dirkgently1

    13 NİSAN 2006
  • jeffisthecoolguy

    jeffisthecoo

    17 HAZİRAN 2013
  • Klemens Torggler

    Klemens Torg

    11 Mart 2008