Aynı anda birden çok değişkeni bildirmenin daha zarif yolu


140

"Aynı anda" birden çok değişken bildirmek için yapardım:

a, b = True, False

Ama çok daha fazla değişken beyan etmek zorunda kalsaydım, daha az zarifleşir:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True

Bunu yapmanın daha iyi / zarif / uygun bir yolu var mı?

Bu çok temel olmalı, ancak değişkenleri saklamak için bir liste veya bir demet kullandığımda, aşağıdaki gibi yardımcı olabilmek için nasıl yaklaşmalıyım:

aList = [a,b]

Geçerli değil, yapmak zorundayım:

a, b = True, True

Ya da neyi özlüyorum?


Bu değerleri saklamak için bir liste mi kullanıyorsunuz? Bir sözlük? (Adlandırılmış) bir grup mu?
Jeff Mercado

@Chris: Oraya gidiyordum. :)
Jeff Mercado

@JeffM: belki ama nasıl yapılacağını bilmiyorum bir listeye ait olmak için tanımlanmış gibi görünüyorlar (tabii ki yanlış olabilirim)
Trufa

3
@Trufa: Değerleri depolayacak çok değişken olduğunu bildirecekseniz, bu zaten bir işarettir ve diğer depolama alternatifleri IMHO'yu düşünmelisiniz.
Jeff Mercado

1
@ user470379 - Adların sadece örnek kod için olduğunu ve Trufa'nın gerçek kodunda bu adları kullanmadığını varsaydım.
Chris Lutz

Yanıtlar:


52

Diğerlerinin de belirttiği gibi, Boole değerleriyle 10 farklı yerel değişken kullanmanın rutininizi yazmanın en iyi yolu olması pek olası değildir (özellikle gerçekten bir harfli isimler varsa :)

Ne yaptığınıza bağlı olarak, sözlük kullanmak mantıklı olabilir. Örneğin, tek harfli bir bayrak kümesi için Boole önayar değerlerini ayarlamak istiyorsanız, bunu yapabilirsiniz:

>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

İsterseniz, bunu tek bir atama ifadesiyle de yapabilirsiniz:

>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
...              **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

İkinci parametre dicttamamen bunun için tasarlanmamıştır: gerçekten, anahtar kelime bağımsız değişkenlerini kullanarak sözlüğün tek tek öğelerini geçersiz kılmanıza izin vermeyi amaçlamaktadır d=False. Yukarıdaki kod, ifadenin sonucunu , çağrılan işleve iletilen **bir dizi anahtar kelime bağımsız değişkenine üfler . Bu kesinlikle sözlük oluşturmanın güvenilir bir yoludur ve insanlar en azından bu deyimi kabul ediyor gibi görünmektedir, ancak bazılarının bunu Unpythonic olarak kabul edebileceğinden şüpheleniyorum. </disclaimer>


Bu kalıbı sık sık kullanacak olursanız, muhtemelen en sezgisel olan başka bir yaklaşım, verilerinizi bayrak adlarıyla (tek karakter dizeleri) eşlenen bayrak değerleri ( True, False) listesi olarak tanımlamaktır . Daha sonra bu veri tanımını, bayrak adlarını bayrak değerleriyle eşleyen ters çevrilmiş bir sözlüğe dönüştürürsünüz. Bu, iç içe geçmiş bir liste kavrayışı ile oldukça kısa bir sürede yapılabilir, ancak işte çok okunabilir bir uygulama:

>>> def invert_dict(inverted_dict):
...     elements = inverted_dict.iteritems()
...     for flag_value, flag_names in elements:
...         for flag_name in flag_names:
...             yield flag_name, flag_value
... 
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Fonksiyon invert_dictbir jeneratör fonksiyonudur . Bu oluşturur , ya da verimi - bu, yani art arda değerlerini döner anahtar-değer çiftleri -. Bu anahtar / değer çiftleri, ilk flagssözlüğün iki öğesinin içeriğinin tersidir . Yapıcıya beslenirler dict. Bu durumda dictyapıcı yukarıdakinden farklı çalışır çünkü argüman olarak bir sözlük yerine bir yineleyici ile beslenir .


@Chris Lutz'un yorumu üzerine çizim: Bunu gerçekten tek karakterli değerler için kullanacaksanız,

>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Bu çalışır, çünkü Python dizeleri yinelenebilir , yani değere göre değere göre hareket ettirilebilir. Bir dize durumunda, değerler dizedeki ayrı karakterlerdir. Yani yinelenebilir olarak yorumlandıklarında, bu durumda bir for döngüsünde kullanıldıkları ['a', 'b', 'c']ve 'abc'etkili bir şekilde eşdeğer oldukları gibi. Başka bir örnek, yinelenebilir bir işlev alan bir işleve geçirildikleri zaman olabilir tuple.

Kişisel olarak bunu yapmazdım çünkü sezgisel olarak okumaz: Bir dize gördüğümde, bir liste yerine tek bir değer olarak kullanılmasını beklerim. Bu yüzden ilk satıra bakıyorum ve "Tamam, bir Gerçek bayrak ve bir Yanlış bayrak var" diye düşünüyorum. Bu bir olasılık olmasına rağmen, bunun bir yol olduğunu düşünmüyorum. Üstte, tekrarlanabilir ve tekrarlayıcı kavramlarını daha açık bir şekilde açıklamaya yardımcı olabilir.


İşlevi invert_dictgerçekte bir sözlük döndürecek şekilde tanımlamak da kötü bir fikir değildir; Çoğunlukla bunu yapmadım çünkü rutinin nasıl çalıştığını açıklamak gerçekten yardımcı olmuyor.


Görünüşe göre Python 2.7, bu işlevi uygulamak için son derece özlü bir yol sağlayacak sözlük kavrayışına sahiptir. Bu, Python 2.7 yüklü olmadığından okuyucuya bir alıştırma olarak bırakıldı :)

Ayrıca, çok yönlü itertools modülünden bazı işlevleri de birleştirebilirsiniz . Dedikleri gibi, Bunu Yapmanın Birden Fazla Yolu Var . Bekle, Python halkı bunu söylemiyor. Bazı durumlarda bu doğrudur. Guido'nun bize sözlük kavrayışları verdiğini, böylece bunu yapmanın Tek Açık Yolu olacağını tahmin ediyorum .


1
Not ['a', 'b', 'c']olarak kısaltılabilir list('abc'), hangi ilham olarak def truth_values(trues, falses): d = dict.from_keys(list(trues), True); d.update(dict.from_keys(list(falses), False)); return dkullanılırvalues = truth_values("abc", "de")
Chris Lutz

Çok teşekkür ederim, bu çok kapsamlı bir cevap gibi görünüyor, ona iyi bakacağım ve nesirlerinizi, söylediklerinizi deneyeceğim, muhtemelen doğru olsa da, doğal gelmeyebilir, bu yüzden yapmam gerekecek Biraz okuyun ve özellikle python'daki zayıf yönlerimden biri olan sözlüklerden beri ne demek istediğini tam olarak elde edene kadar oynayın. Çok teşekkür ederim, geri döneceğim :)
Trufa

5
Cevabınız beni çok şaşırttı: OP'nin probleminden başka bir problem tanımladınız ve bu diğer soruna uzun bir cevap vermekten mutluluk duyuyorsunuz. Sözlükteki dizeleri ve değerleri ilişkilendirmek istemez, her biri için bir tanımlayıcı ve değer içeren nesneler oluşturmak ister.
eyquem

5
@eyquem: Uzun cevaplar kötü mü? Doktor, kendini iyileştir!
John Machin

5
Bu soruya cevap vermiyor ve patlayıcı oluyor. Aşağıdaki cevaba bakınız
kodu

225
a, b, c, d, e, g, h, i, j = (True,)*9
f = False

21
@Imray Sonunda virgül gösterimi (d,), bir dizi türü olan tek öğeli bir grup oluşturur. Dizi türleri , diğer işlemlerin yanı sıra toplama ve çarpmayı destekler.
duozmo

36
Zarif numara, ancak bunu listeler gibi değişebilir öğeler üzerinde kullandığınızı unutmayın. Örneğin a, b, c = ([],)*33 liste örneklerini ancak yapar yaratmaz a, bve caynı örneğe işaret.
Zac

5
Python kodumu uber pythonic yapmaya çalışırken harcadığım / harcadığım zamanı çok merak ediyorum.
SARose

3
@Zac doğru yapmak için kullanın a, b, c = ([] for i in range(3)). kaynak . Tutarlılık için, bu cevap için bunun bir varyantını da kullanabilirsiniz, yani a,b,c,d,e,g,h,i,j = (True for i in range(9)) f=(False i in range(1)).
Acemi C

Python'u neden sevdiğime bir örnek, Sadece son zamanlarda kullanıyorum .. Keşke daha erken başlıyor .. Ama web geliştirme projeye bağlı olarak değişiyor.
Kızgın 84

52

Tanımladığınız şeyleri özetlemek için bir liste / sözlük kullanın veya kendi sınıfınızı tanımlayın, ancak tüm bu değişkenlere ihtiyacınız varsa şunları yapabilirsiniz:

a = b = c = d = e = g = h = i = j = True
f = False

1
vars yalnızca True & False olarak ayarlanmaz.
N 1.1

1
@ N1.1: Bununla ne demek istediğini anlayamadım.
Trufa

@Trufa Yalnızca Doğru / Yanlış olarak ayarlanırsa, önerilen yol mükemmeldir, ancak değişkenler farklı şeylere ayarlanmışsa ne olur?
N 1.1

@ N1.1: Ohh Ne demek istediğini anlıyorum, açıklama için teşekkürler! Bu durumda, hepsi bools ama bilmek güzel. Teşekkürler
Trufa

5
Bunun neden tehlikeli bir model olduğunu açıklamak için (çalışma örneği de olsa), Notorious BIG
duozmo hakkında bilgi alın

10

Bu @ Jeff M ve yorumlarım hakkında bir ayrıntı .

Bunu yaptığınızda:

a, b = c, d

Tuple paketleme ve açma ile çalışır. Paketleme ve paketleme adımlarını ayırabilirsiniz:

_ = c, d
a, b = _

İlk satır _, birincisi değeri cve ikincisi değeri olan iki öğeye sahip denilen bir demet oluşturur d. İkinci satır ise _tuple değişkenini ave b. Bu büyük bir çizginizi yıkıyor:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True

İki küçük satıra:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _

Size ilk satırla aynı sonucu verir (bir bölüme değer veya değişken ekler ancak diğerini güncellemeyi unutursanız aynı istisna dahil). Ancak, bu özel durumda, yan cevabı belki de en iyisidir.

Değerler listeniz varsa, bunları yine de açabilirsiniz. Sadece önce bir tuple dönüştürmek gerekir. Örneğin, aşağıdaki her bir için 0 ile 9 arasında bir değer atar athrough jsırasıyla:

a, b, c, d, e, f, g, h, i, j = tuple(range(10))

EDIT: 5 (değişken f) öğesi dışında hepsini doğru olarak atamak için düzgün hile :

a, b, c, d, e, f, g, h, i, j = tuple(x != 5 for x in range(10))

Sonuncunun mümkün olduğunu bilmiyordum, kesinlikle bir deneyeceğim, gerçekten temiz bir numara ve kullanışlı olabilir!
Trufa

5

İnsanlar "bir liste veya grup veya başka bir veri yapısı kullan" önerdiklerinde, önem verdiğiniz birçok farklı değere sahip olduğunuzda, bunları yerel değişkenler olarak ayrı ayrı adlandırmanın en iyi yolu olmayabileceği söylenir. bir şeyler yapmak.

Bunun yerine, bunları tek bir yerel değişkende saklanabilecek daha büyük bir veri yapısında bir araya getirmek isteyebilirsiniz.

sezgisel olarak bunun için bir sözlüğü nasıl kullanabileceğinizi ve Chris Lutz ayrı değişkenlere açmadan önce geçici depolama için bir tuple nasıl kullanılacağını gösterdi, ancak dikkate alınması gereken başka bir seçenek collections.namedtuplede değerleri daha kalıcı bir şekilde paketlemek için kullanmaktır .

Yani şöyle bir şey yapabilirsiniz:

# Define the attributes of our named tuple
from collections import namedtuple
DataHolder = namedtuple("DataHolder", "a b c d e f g")

# Store our data
data = DataHolder(True, True, True, True, True, False, True)

# Retrieve our data
print(data)
print(data.a, data.f)

Gerçek kod, umarım "DataHolder" ve alfabenin harflerinden daha anlamlı isimler kullanır.


Cevabınız için teşekkür ederim, bunu bir seçenek olarak kontrol edeceğim, şey şu ki ( bu özel durum için ) sahip olmak ve değişmez bir yapıya sahip olmak yararlı olmayabilir. Daha sonra bunun nasıl olduğu hakkında yorum yapacağım, yine çok teşekkürler!
Trufa

Aynı şeyi sıradan bir sınıfla da yapabilirsiniz - tanımı DataHolderbiraz daha ayrıntılı olur.
ncoghlan

4

Aslında sorun ne?

Gerçekten ihtiyacınız yoksa istiyorsanız 10 a , b , c , d , e , f , g , h , i , j , yazmaya, bir kez ya da başka, başka bir olanağı yok olacak bir ve yazma b ve yazma c . ....

Değerlerin hepsi farklıysa, örnek için yazmak zorunda kalacaksınız

a = 12
b= 'sun'
c = A() #(where A is a class)
d = range(1,102,5)
e = (line in filehandler if line.rstrip())
f = 0,12358
g = True
h = random.choice
i = re.compile('^(!=  ab).+?<span>')
j = [78,89,90,0]

yani "değişkenlerin" ayrı ayrı tanımlanmasıdır.

Veya başka bir yazı kullanarak aşağıdakileri kullanmanıza gerek yoktur _:

a,b,c,d,e,f,g,h,i,j =\
12,'sun',A(),range(1,102,5),\
(line for line in filehandler if line.rstrip()),\
0.12358,True,random.choice,\
re.compile('^(!=  ab).+?<span>'),[78,89,90,0]

veya

a,b,c,d,e,f,g,h,i,j =\
(12,'sun',A(),range(1,102,5),
 (line for line in filehandler if line.rstrip()),
 0.12358,True,random.choice,
 re.compile('^(!=  ab).+?<span>'),[78,89,90,0])

.

Bazılarının aynı değere sahip olması gerekiyorsa, yazmak için çok uzun olan sorun

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True 

?

Sonra yazabilirsiniz:

a=b=c=d=e=g=h=i=k=j=True
f = False

.

Senin sorununun tam olarak ne olduğunu anlamıyorum. Bir kod yazmak istiyorsanız, talimatların ve tanımların yazılması için gereken karakterleri kullanmak zorundasınız. Başka ?

Sorunuzun bir şeyi yanlış anladığınızın işareti olup olmadığını merak ediyorum.

Birisi yazdığında a = 10, "değeri değişebilen bellek yığını" anlamında bir değişken yaratmaz . Bu talimat:

  • integer10 türü ve değeri olan bir nesnenin oluşturulmasını ve 'a' adının geçerli ad alanında bu nesneyle bağlanmasını tetikler

  • veya ad alanındaki 'a' adını 10 nesnesine yeniden atayın (çünkü 'a' daha önce başka bir nesneye bağlanmıştır)

Bunu söylüyorum çünkü Yanlış, Doğru işaret eden 10 tanımlayıcı a, b, c ... tanımlayan yardımcı programı göremiyorum. Bu değerler yürütme sırasında değişmezse, neden 10 tanımlayıcı? Ve eğer değişirlerse, neden önce tanımlayıcıları tanımlamak gerekir?

Sorunuz bana garip geliyor


2

Görünüşe göre problemin bana yanlış yaklaşıyor.

Bir demet kullanmak için kodunuzu yeniden yazın veya tüm verileri saklamak için bir sınıf yazın.


Kodun bir an bile görülmeden söyleyebildiğiniz için teşekkür ederim :) Bunun ideal olmadığını anlıyorum ve yeniden biçimlendirmek zorunda kalabilirim, ancak cevabınız soruyu gerçekten çözmüyor. Ne demek istediğimi anlıyorum.
Trufa

1
Kulağa böyle geldiğini söyleyebilirim, evet. Kulağa böyle geliyor. Yeniden düzenleme büyük olasılıkla sorununuzu çözecektir. Sorununuz bir stil sorunu, fonksiyonel bir sorun değil, bu yüzden oldukça metadvice'den başka bir şey sunmak zor.
richo

1

En çok oy alan yanıtı beğendim; ancak, gösterildiği gibi liste ile ilgili sorunları var.

  >> a, b = ([0]*5,)*2
  >> print b
  [0, 0, 0, 0, 0]
  >> a[0] = 1
  >> print b
  [1, 0, 0, 0, 0]

Bu büyük ayrıntılarda tartışılmaktadır (burada) , ama özü budur ave geri dönen (aynı ) bolan aynı nesnedir . Eğer bir dizin değiştirmek nedenle eğer, her iki dizinini değişiyor ve onlar birbirine bağlı olduğundan,. Bunu çözmek için yapabilirsiniz (kaynak)a is bTrueid(a) == id(b)ab

>> a, b = ([0]*5 for i in range(2))
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[0, 0, 0, 0, 0]

Bu daha sonra "istenen" sezgisel sonuçlara sahip olan üst cevabın bir varyantı olarak kullanılabilir

>> a, b, c, d, e, g, h, i = (True for i in range(9))
>> f = (False for i in range(1)) #to be pedantic

1

Senin durumunda, YAML kullanırdım.

Bu, çoklu parametrelerle uğraşmak için zarif ve profesyonel bir standarttır. Değerler ayrı bir dosyadan yüklenir. Bu bağlantıda bazı bilgiler görebilirsiniz:

https://keleshev.com/yaml-quick-introduction

Ancak Google için daha kolay, standart olduğu için, yüzlerce bilgi var, anlayışınıza en uygun olanı bulabilirsiniz. ;)

Saygılarımla.


Merhaba Henrique, SO'ya hoş geldiniz, cevabınız için teşekkür ederim! Lütfen bir sonraki sorunuza cevap vermeden önce bir cevap yazmayı okuduğunuzdan emin olun !
Diggy.

0

JavaScript gibi , python'daki bir satırda birden çok ifade kullanabilirsiniza = 1; b = "Hello World"; c += 3

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.