2010-11-17 38 views
6

Chức năng của tôi mong đợi một danh sách hoặc một bộ dữ liệu làm tham số. Nó không thực sự quan tâm mà nó là tất cả nó làm là vượt qua nó đến một chức năng chấp nhận hoặc là một danh sách hoặc tuple:Tham số hàm Python: tuple/list

def func(arg): # arg is tuple or list 
    another_func(x) 
    # do other stuff here 

Bây giờ tôi cần phải thay đổi chức năng một chút, để xử lý một yếu tố bổ sung:

def func(arg): #arg is tuple or list 
    another_func(x + ['a']) 
    # etc 

Thật không may điều này sẽ không hoạt động: nếu arg là tuple, tôi phải nói x + ('a',).

Rõ ràng, tôi có thể làm cho nó hoạt động bằng cách ép arg vào danh sách. Nhưng nó không gọn gàng.

Có cách nào tốt hơn để làm điều đó không? Tôi không thể ép buộc người gọi luôn luôn vượt qua một tuple, tất nhiên, vì nó chỉ đơn giản là chuyển sang làm việc với họ.

+0

Nếu chức năng khác chấp nhận hoặc hơn tôi sẽ gửi cho nó một bộ tuple vì bạn sẽ làm việc nhanh hơn. Sau đó, những gì không gọn gàng về 'tuple (x) + ('a',)'? – aaronasterling

+0

Tuples có nhanh hơn trong quá trình triển khai không? – max

+2

xây dựng một bộ tuple từ chuỗi ký tự và chuỗi số nhanh hơn việc xây dựng danh sách. Quan trọng hơn, 'tuple (x)' chỉ trả về 'x' nếu nó đã là một tuple trong khi' list (x) 'copy' x' ngay cả khi nó đã là một danh sách. Vì vậy, bằng cách sử dụng một tuple, bạn cắt giảm hầu hết các công việc ra cho một nửa số trường hợp đầu vào của bạn. – aaronasterling

Trả lời

7

Nếu another_func chỉ muốn lặp lại, bạn có thể vượt qua itertools.chain(x,'a').

+0

+1 Tôi thích điều này nhưng nó có nhanh không? – max

+0

@max Không sao chép được thực hiện, vì vậy nó rất nhanh. Đây có lẽ là giải pháp Python hiệu quả nhất. –

3

thế nào về:

l = ['a'] 
l.extend(x) 

Edit: Đọc lại câu hỏi, tôi nghĩ rằng đây là nhiều hơn những gì bạn muốn (việc sử dụng argx là một chút bối rối):

tuple(arg) + ('a',) 

Như những người khác đã nói, đây có lẽ không phải là cách hiệu quả nhất, nhưng nó rất rõ ràng. Nếu danh sách/danh sách của bạn nhỏ, tôi có thể sử dụng các giải pháp này ít hơn rõ ràng vì hiệu suất đạt được sẽ không đáng kể. Nếu danh sách của bạn lớn, hãy sử dụng các giải pháp hiệu quả hơn.

+0

'mở rộng' trả về' Không có', vì nó biến đổi danh sách. – delnan

+0

+1, đơn giản và sạch sẽ – slezica

+0

@delnan: ý của bạn là gì? – max

4

Điều gì sẽ thay đổi chức năng khác để chấp nhận danh sách các thông số thay thế?

def func(arg): # arg is tuple or list 
    another_func('a', *x) 
+1

Điều gì về khi another_func cần một số đối số danh sách bị ảnh hưởng bởi cùng một vấn đề hoặc nếu nó đã có tham số * x không liên quan? – max

+0

+0: tốt nhưng không chắc chắn nếu func khác có thể được thay đổi – Claudiu

+0

@ max: Câu trả lời là như nhau. Sửa chức năng khác. –

2
def f(*args): 
    print args 

def a(*args): 
    k = list(args) 
    k.append('a') 
    f(*k) 

a(1, 2, 3) 

Output:

(1, 2, 3, 'a') 
+0

hmm 'f (* (tuple (args) + ('a',))' là tốt hơn – Claudiu

1

Đề nghị của tôi:

def foo(t): 
    bar(list(t) + [other]) 

Đây không phải là rất hiệu quả tuy nhiên, bạn muốn được tốt hơn thông qua những thứ xung quanh có thể thay đổi nếu bạn đang đi để được , tốt, thay đổi chúng.

+0

Bạn có thể làm rõ không? Tại sao điều này không hiệu quả? – max

+0

@max Nó không hiệu quả vì nó sao chép toàn bộ danh sách chỉ để thêm –

0

Chức năng của bạn có chấp nhận bất kỳ lần lặp nào không. Sau đó, sử dụng itertools.chain để thêm bất kỳ chuỗi nào bạn muốn lặp lại.

from itertools import chain 

def func(iterable): 
    another_func(chain(iterable, ('a',))) 
1

Bạn có thể sử dụng các loại của iterable truyền cho hàm đầu tiên để xây dựng những gì bạn vượt qua thứ hai:

from itertools import chain 

def func(iterable): 
    it = iter(iterable) 
    another_func(type(iterable)(chain(it, ('a',)))) 

def another_func(arg): 
    print arg 

func((1,2)) 
# (1, 2, 'a') 
func([1,2]) 
# [1, 2, 'a'] 
2

Nếu một iterable là đủ, bạn có thể sử dụng itertools.chain, nhưng lưu ý rằng nếu hàm A (cái đầu tiên được gọi), cũng lặp lại qua vòng lặp có thể lặp lại sau khi gọi B, thì bạn có thể gặp vấn đề vì các vòng lặp không thể được tua lại.Trong trường hợp này, bạn nên lựa chọn cho một chuỗi hoặc sử dụng iterable.tee để tạo một bản sao của iterable:

import itertools as it 

def A(iterable): 
    iterable, backup = it.tee(iterable) 
    res = B(it.chain(iterable, 'a')) 
    #do something with res 
    for elem in backup: 
     #do something with elem 

def B(iterable): 
    for elem in iterable: 
     #do something with elem 

Mặc dù itertools.tee là không thực sự là hiệu quả nếu B tiêu thụ tất cả hoặc nhất của iterable, tại thời điểm đó, đơn giản chỉ cần chuyển đổi iterable thành tuple hoặc list.

+0

+1 để làm rõ về việc tua lại các trình lặp, trong trường hợp của tôi, có thể lặp lại là đủ, tôi đoán cho trường hợp trình tự, tôi sẽ kết hợp với tuple theo gợi ý của @aaronasterling – max

0

tôi muốn nói câu trả lời làm

def foo(t): 
    bar(list(t) + [other]) 

Santiago Lezica là tốt nhất bởi vì nó là đơn giản nhất. (không cần phải nhập công cụ itertools và sử dụng các cuộc gọi chuỗi ít có thể đọc được nhiều hơn). Nhưng chỉ sử dụng nó nếu bạn mong đợi t được nhỏ. Nếu t có thể lớn, bạn nên sử dụng một trong các giải pháp khác.

Các vấn đề liên quan