Đối tượng Ellipsis làm gì?


539

Trong khi lướt qua không gian tên, tôi nhận thấy một đối tượng trông kỳ quặc được gọi Ellipsis, nó dường như không hoặc không làm gì đặc biệt, nhưng đó là một nội dung có sẵn trên toàn cầu.

Sau khi tìm kiếm, tôi thấy rằng nó được sử dụng trong một số biến thể tối nghĩa của cú pháp cắt của Numpy và Scipy ... nhưng hầu như không có gì khác.

Có phải đối tượng này đã được thêm vào ngôn ngữ để hỗ trợ Numpy + Scipy? Ellipsis có bất kỳ ý nghĩa chung hoặc sử dụng ở tất cả?

D:\workspace\numpy>python
Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> Ellipsis
Ellipsis

Xem câu trả lời cho stackoverflow.com/questions/752602/
Mạnh

19
Tôi tìm thấy nó như thế này: Tôi đã nhập x=[];x.append(x);print(x), để xem cách nó xử lý xâu chuỗi các đối tượng theo chu kỳ. Nó trở về [[...]]. Tôi nghĩ "Tôi tự hỏi chuyện gì sẽ xảy ra nếu tôi gõ [[...]]? Tôi đoán là nó sẽ gây ra lỗi cú pháp. Thay vào đó, nó trở lại [[Ellipsis]]. Python rất kỳ lạ. Tìm kiếm Google đã đưa tôi đến trang này.
Cyoce

22
lưu ý rằng ...trong một repr đệ quy chỉ là một giữ chỗ và không có liên quan đếnEllipsis
Eevee

16
Trên một lưu ý hoàn toàn, ba dấu chấm trong nhập có nghĩa là "nhập từ hai gói trở lên".
Nhà vật lý điên

1
@croq stackoverflow.com/q/32395926/2988730 . stackoverflow.com/q/1054271/2988730 . Hai người đó nên giải thích mọi thứ, với các liên kết thích hợp đến tài liệu và PEP trong câu trả lời.
Nhà vật lý điên

Câu trả lời:


558

Điều này xuất hiện trong một câu hỏi khác gần đây. Tôi sẽ giải thích câu trả lời của tôi từ đó:

Dấu chấm lửng là một đối tượng có thể xuất hiện trong ký hiệu lát. Ví dụ:

myList[1:2, ..., 0]

Giải thích của nó hoàn toàn tùy thuộc vào bất cứ điều gì thực hiện __getitem__chức năng và nhìn thấy Ellipsiscác đối tượng ở đó, nhưng việc sử dụng chính (và dự định) của nó là trong thư viện của bên thứ ba numpy , có thêm kiểu mảng đa chiều. Vì có nhiều hơn một chiều, việc cắt lát trở nên phức tạp hơn chỉ là chỉ số bắt đầu và dừng; nó cũng hữu ích để có thể cắt theo nhiều chiều. Ví dụ, được đưa ra một mảng 4 x 4, khu vực trên cùng bên trái sẽ được xác định bởi lát cắt [:2,:2]:

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

>>> a[:2,:2]  # top left
array([[1, 2],
       [5, 6]])

Mở rộng điều này hơn nữa, Ellipsis được sử dụng ở đây để chỉ ra một trình giữ chỗ cho phần còn lại của kích thước mảng không được chỉ định. Hãy nghĩ về nó như chỉ ra lát cắt đầy đủ [:]cho tất cả các kích thước trong khoảng trống được đặt, do đó, đối với mảng 3d, a[...,0]cũng giống như a[:,:,0]và đối với 4d a[:,:,:,0], tương tự, a[0,...,0]a[0,:,:,0](với nhiều dấu hai chấm ở giữa tạo thành số đầy đủ kích thước trong mảng).

Thật thú vị, trong python3, Ellipsis bằng chữ ( ...) có thể sử dụng được ngoài cú pháp lát, vì vậy bạn thực sự có thể viết:

>>> ...
Ellipsis

Khác với các loại số khác nhau, không, tôi không nghĩ rằng nó được sử dụng. Theo như tôi biết, nó đã được thêm vào hoàn toàn cho việc sử dụng numpy và không có hỗ trợ cốt lõi nào ngoài việc cung cấp đối tượng và cú pháp tương ứng. Đối tượng ở đó không yêu cầu điều này, nhưng sự hỗ trợ "..." theo nghĩa đen cho các lát cắt đã làm.


22
nó cũng được sử dụng trong gợi ý loại PEP484 trong các tệp sơ khai
noɥʇʎԀʎzɐɹƆ

24
Chỉ trong trường hợp bất kỳ ai cũng tò mò: nó cũng được sử dụng trong typingmô-đun thư viện tiêu chuẩn : ví dụ Callable[..., int]để chỉ ra một cuộc gọi có thể trả về intmà không chỉ định chữ ký hoặc Tuple[str, ...]để chỉ ra một chuỗi các chuỗi đồng nhất có độ dài thay đổi.
Anakhand

6
FYI, khung FastAPI (dành cho python 3.6+) cũng (hiện tại) sử dụng nó. fastapi.tiangolo.com/tutorial/query-params-str-validations
Andrew Allaire

2
@ArtOfWarfare bạn hoàn toàn đúng, và điều này đến từ một người nói bằng lời nói "dấu chấm lửng" thay vì thoát ra giữa các câu.
PrimeRibeyeDeal

Tôi đã tìm thấy cái này. Nó dường như xuất hiện khi bạn thực hiện tự tham chiếu (tham chiếu vòng tròn) trong danh sách: a = [1, 2]; a[0] = a; print(a)cho [[...], 2]. Đây là cùng một điều hoặc sử dụng khác nhau?
Hóa đơn

220

Trong Python 3, bạn có thể sử dụng nghĩa đen của Ellipsis ...như một trình giữ chỗ trên mạng của nop

def will_do_something():
    ...

Đây không phải là phép thuật; bất kỳ biểu thức nào cũng có thể được sử dụng thay vì ..., vd:

def will_do_something():
    1

(Không thể sử dụng từ ngữ bị xử phạt, nhưng tôi có thể nói rằng việc sử dụng này không bị Guido từ chối hoàn toàn .)


181
Trong một nửa quy ước, tôi thường thấy ...được sử dụng ở nơi mọi người muốn chỉ ra thứ gì đó họ dự định điền vào sau (khối trống 'todo') và passcó nghĩa là một khối dự định không có mã.
Gareth Latty

26
Python cũng có NotImplementednghĩa đen, rất hữu ích khi bạn muốn hàm không hoàn chỉnh của mình trả về một cái gì đó có ý nghĩa (thay vì Nonenhư trong ví dụ của bạn). (Một usecase khác: Thực hiện các phép toán số học )
zvyn

13
@zvyn Đó không phải là nghĩa đen. Đó chỉ là một cái tên. Ví dụ NotImplemented = 'something_else'là python hợp lệ, nhưng ... = 'something_else'là một lỗi cú pháp.
wim

4
@zvyn Điều gì xảy ra nếu một ngoại lệ xảy ra trong khi nhập mô-đun đó? :)
pizzapants184

7
@zvyn NotImplementedkhông có ý định thay thế None. Cách sử dụng của nó khá hẹp. Xem tài liệu ở đây
hans

69

Kể từ Python 3.5 và PEP484 , dấu chấm lửng được sử dụng để biểu thị một số loại nhất định cho trình kiểm tra kiểu tĩnh khi sử dụng mô-đun .

Ví dụ 1:

Các bộ dữ liệu đồng nhất có độ dài tùy ý có thể được biểu thị bằng một loại và dấu chấm lửng, ví dụ Tuple[int, ...]

Ví dụ 2:

Có thể khai báo kiểu trả về của một cuộc gọi mà không cần chỉ định chữ ký cuộc gọi bằng cách thay thế dấu chấm lửng bằng chữ (ba dấu chấm) cho danh sách các đối số:

def partial(func: Callable[..., str], *args) -> Callable[..., str]:
    # Body

46

Bạn cũng có thể sử dụng Ellipsis khi chỉ định đầu ra doctest dự kiến :

class MyClass(object):
    """Example of a doctest Ellipsis

    >>> thing = MyClass()
    >>> # Match <class '__main__.MyClass'> and <class '%(module).MyClass'>
    >>> type(thing)           # doctest:+ELLIPSIS
    <class '....MyClass'>
    """
    pass

9
Nhưng điều này thực sự liên quan đến đối tượng Ellipsis? Không phải nó chỉ là một tính năng của trình phân tích cú pháp / trình so khớp doctest sao?
akaihola

1
@akaihola Tôi muốn nói rằng, như được mô tả tại doctest.ELLIPSIS . Tôi hy vọng rằng hầu hết nếu không phải tất cả các cách sử dụng ...là cú pháp và không phải uselà đối tượng Ellipsis thực tế. Nó thực sự không có gì khác hơn là một cái tên tiện dụng cho một khái niệm có thể thích nghi?
nealmcb

34

Từ tài liệu Python :

Đối tượng này thường được sử dụng bằng cách cắt lát (xem phần Cắt lát ). Nó hỗ trợ không có hoạt động đặc biệt. Có chính xác một đối tượng dấu chấm lửng, được đặt tên là Ellipsis (tên tích hợp). type(Ellipsis)()sản xuất đĩa đơn Ellipsis.

Nó được viết là Ellipsishoặc ....


25

Tóm tắt những gì người khác đã nói, kể từ Python 3, Ellipsis về cơ bản là một hằng số đơn lẻ tương tự None, nhưng không có mục đích sử dụng cụ thể. Sử dụng hiện tại bao gồm:

  • Trong cú pháp lát để thể hiện lát cắt đầy đủ trong các kích thước còn lại
  • Trong gợi ý loại chỉ để chỉ một phần của loại ( Callable[..., int]hoặc Tuple[str, ...])
  • Trong các loại tệp sơ khai để chỉ ra có một giá trị mặc định mà không chỉ định nó

Sử dụng có thể có thể bao gồm:

  • Là một giá trị mặc định cho những nơi Nonelà một tùy chọn hợp lệ
  • Là nội dung cho một chức năng bạn chưa triển khai

14

__getitem__...ví dụ tối thiểu trong một lớp tùy chỉnh

Khi cú pháp ma thuật ...được chuyển đến []trong một lớp tùy chỉnh, __getitem__()sẽ nhận được một Ellipsisđối tượng lớp.

Lớp sau đó có thể làm bất cứ điều gì nó muốn với đối tượng Singleton này.

Thí dụ:

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# Ellipsis notation generates the Ellipsis class object.
# Ellipsis is a singleton, so we can compare with `is`.
assert C()[...] is Ellipsis

# Everything mixed up.
assert C()[1, 2:3:4, ..., 6] == (1, slice(2,3,4), Ellipsis, 6)

Lớp tích hợp Python listchọn cung cấp cho nó ngữ nghĩa của một phạm vi và tất nhiên mọi cách sử dụng lành mạnh của nó cũng nên.

Cá nhân, tôi chỉ cần tránh xa nó trong API của mình và tạo một phương thức rõ ràng hơn, riêng biệt hơn.

Đã thử nghiệm trong Python 3.5.2 và 2.7.12.


chạy điều này với đối số -O và mã của bạn sẽ luôn chạy; D
moshevi


7

Như được đề cập bởi @ noɥʇʎԀʎzɐɹƆ và @phoenix - Bạn thực sự có thể sử dụng nó trong các tệp sơ khai. ví dụ

class Foo:
    bar: Any = ...
    def __init__(self, name: str=...) -> None: ...

Thông tin chi tiết và ví dụ về cách sử dụng dấu chấm lửng này có thể được tìm thấy tại đây https://www.python.org/dev/peps/pep-0484/#stub-files


2

Mục đích sử dụng của nó không nên chỉ dành cho các mô-đun bên thứ 3 này. Nó không được đề cập đúng trong tài liệu Python (hoặc có lẽ tôi không thể tìm thấy điều đó) nhưng dấu chấm lửng ...thực sự được sử dụng trong CPython ở ít nhất một nơi.

Nó được sử dụng để biểu diễn các cấu trúc dữ liệu vô hạn trong Python. Tôi đã gặp ký hiệu này trong khi chơi xung quanh với các danh sách.

Xem câu hỏi này để biết thêm.


8
Những điều khác nhau. Câu hỏi này hỏi về ellipsisloại tích hợp và Ellipsisđối tượng. Việc biểu diễn các cấu trúc dữ liệu vô hạn bằng các hình elip hoàn toàn để hiển thị, không liên quan gì đến ellipsisloại hoặc Ellipsisđối tượng.
chys

3
@chys Trên thực tế, nó thực hiện theo một cách nhỏ - __repr__Chuỗi Python nhắm đến các biểu thức Python hợp lệ - nếu không phải là dấu chấm lửng tồn tại trong ngôn ngữ như hiện tại, thì biểu diễn sẽ không phải là biểu thức hợp lệ.
Gareth Latty

3
@Lattyware Vâng, đúng là thiết kế ban đầu rất có ý định. Nó cũng dự định eval(repr(a))nhằm mục đích để được bằng a. Thật không may, đôi khi nó sai trong thực tế, ngay cả đối với các loại tích hợp. Hãy thử điều này : a=[]; a.append(a); eval(repr(a)). repr(a)[[...]], biểu thức không hợp lệ trong Python 2. (Trong Python 3 nó hợp lệ, nhưng kết quả eval là một cái gì đó khác, vẫn trái với ý định ban đầu.)
chys

1

Điều này là tương đương.

l=[..., 1,2,3]
l=[Ellipsis, 1,2,3]

...là một hằng số được xác định bên trong built-in constants.

Dấu chấm lửng

Giống như dấu chấm lửng theo nghĩa đen của ... Giá trị đặc biệt được sử dụng chủ yếu kết hợp với cú pháp cắt lát mở rộng cho các kiểu dữ liệu chứa do người dùng xác định.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.