W JavaScript, mogę używać destrucructing, aby wyodrębnić właściwości, które chcę z JavaScript obiekty w jednej wkładce. Na przykład:

currentUser = {
  "id": 24,
  "name": "John Doe",
  "website": "http://mywebsite.com",
  "description": "I am an actor",
  "email": "example@example.com",
  "gender": "M",
  "phone_number": "+12345678",
  "username": "johndoe",
  "birth_date": "1991-02-23",
  "followers": 46263,
  "following": 345,
  "like": 204,
  "comments": 9
}

let { id, username } = this.currentUser;
console.log(id) // 24
console.log(username) //johndoe

Czy mamy coś podobnego w Pythonie do Dyktów Pythona i obiektów Pythona? Przykład Drogi Pythona dla obiektów Pythona:

class User:
    def __init__(self, id, name, website, description, email, gender, phone_number, username):
        self.id = id
        self.name = name
        self.website = website
        self.description = description
        self.email = email
        self.gender = gender
        self.phone_number = phone_number
        self.username = username

current_user = User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "example@example.com", "M", "+12345678", "johndoe")

# This is a pain
id = current_user.id
email = current_user.email
gender = current_user.gender
username = current_user.username

print(id, email, gender, username)

Pisanie tych 4 linii (jak wspomniano w przykładzie powyżej) vs pisania pojedynczej linii (jak wspomniano poniżej), aby pobrać wartości potrzebne z obiektu to prawdziwy punkt bólu.

(id, email, gender, username) = current_user
41
Lokesh Agrawal 20 luty 2019, 14:22

4 odpowiedzi

Najlepsza odpowiedź

Nie spłaszczaj argumentów na pierwszym miejscu. Po napisaniu funkcji 8-ary, tak jak zrobiłeś z User, musisz popełnić błędy, takie jak przechodzące argumenty w niewłaściwym porządku.

Które z poniższych wytwarza użytkownik, który zamierzasz?

  1. User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "example@example.com", "M", "+12345678", "johndoe")
  2. User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "example@example.com", "+12345678", "M", "johndoe")

Niemożliwe wiedzieć! Jeśli Twoja funkcja ma deskryptor, nie masz tego problemu -

class User:
  def __init__ (self, desc = {}):
    self.desc = desc # whitelist items, if necessary
  
  def __str__ (self):
    # invent our own "destructuring" syntax
    [ name, age, gender ] = \
      destructure(self.desc, 'name', 'age', 'gender')

    return f"{name} ({gender}) is {age} years old"

# create users with a "descriptor"
u = User({ 'age': 2, 'gender': 'M' })
v = User({ 'gender': 'F', 'age': 3 })
x = User({ 'gender': 'F', 'name': 'Alice', 'age': 4 })

print(u) # None (M) is 2 years old
print(v) # None (F) is 3 years old
print(x) # Alice (F) is 4 years old

Możemy zdefiniować nasze własne destructure jako -

def destructure (d, *keys):
  return [ d[k] if k in d else None for k in keys ]

Nadal może to spowodować długie łańcuchy, ale zamówienie zależy od dzwoniącego, dlatego nie jest kruche jak funkcja 8-ary w pierwotnym pytaniu -

[ name, age, gender ] = \
  destructure(self.desc, 'name', 'age', 'gender')

# works the same as

[ gender, name, age ] = \
  destructure(self.desc, 'gender', 'name', 'age')

Inną opcją jest użycie argumentów słów kluczowych -

class User:
  def __init__ (self, **desc):
    self.desc = desc # whitelist items, if necessary

  def __str__ (self):
    [ name, age, gender ] = \
      destructure(self.desc, 'name', 'age', 'gender')

    return f"{name} ({gender}) is {age} years old"

# create users with keyword arguments
u = User(age = 2, gender = 'M')
v = User(gender = 'F', age = 3)
x = User(gender = 'F', name = 'Alice', age = 4)

print(u) # None (M) is 2 years old
print(v) # None (F) is 3 years old
print(x) # Alice (F) is 4 years old
5
Ricardo Stuven 30 sierpień 2020, 23:52

Budowanie innych odpowiedzi, polecam również użycie Pythona {X0}} i użyj __getitem__, aby uzyskać określone pola:

from dataclasses import astuple, dataclass

@dataclass
class User:
    id: int
    name: str
    website: str
    description: str
    email: str
    gender: str
    phone_number: str
    username: str
    
    def __iter__(self):
        return iter(astuple(self))
    
    def __getitem__(self, keys):
        return iter(getattr(self, k) for k in keys)
        

current_user = User(id=24, name="Jon Doe", website="http://mywebsite.com", description="I am an actor", email="example@example.com", gender="M", phone_number="+12345678", username="johndoe")

# Access fields sequentially:
id, _, email, *_ = current_user
# Access fields out of order:
id, email, gender, username = current_user["id", "email", "gender", "username"]
1
Carl G 18 wrzesień 2020, 19:28

Możesz zniszczyć słownika Pythona i wyodrębnić właściwości, rozpakowując metodą .values():

 currentUser = {
  "id": 24,
  "name": "John Doe",
  "website": "http://mywebsite.com",
  "description": "I am an actor",
  "email": "example@example.com",
  "gender": "M",
  "phone_number": "+12345678",
  "username": "johndoe",
  "birth_date": "1991-02-23",
  "followers": 46263,
  "following": 345,
  "like": 204,
  "comments": 9
}

id, _, _, _, _, _, _, username, *other = currentUser.values()

print('distructuring:', { 'id': id, 'username': username })
2
Roman 25 październik 2020, 07:20

Możesz użyć operator moduł z biblioteki standardowej w następujący sposób:

from operator import attrgetter
id, email, gender, username = attrgetter('id', 'email', 'gender', 'username')(current_user)
print(id, email, gender, username)

W przypadku masz dict jak z twojego przykładu

currentUser = {
  "id": 24,
  "name": "John Doe",
  "website": "http://mywebsite.com",
  "description": "I am an actor",
  "email": "example@example.com",
  "gender": "M",
  "phone_number": "+12345678",
  "username": "johndoe",
  "birth_date": "1991-02-23",
  "followers": 46263,
  "following": 345,
  "like": 204,
  "comments": 9
}

Po prostu użyj itemgetter zamiast attrgetter:

from operator import itemgetter
id, email, gender, username = itemgetter('id', 'email', 'gender', 'username')(currentUser)
print(id, email, gender, username)
6
Ricardo Stuven 30 sierpień 2020, 23:55