Rock It 《ML》JupyterLab 【丁】Code《三》

為什麼『元祖』

4.6.5. Tuples

Tuples are immutable sequences, typically used to store collections of heterogeneous data (such as the 2-tuples produced by the enumerate() built-in). Tuples are also used for cases where an immutable sequence of homogeneous data is needed (such as allowing storage in a set or dict instance).

class tuple([iterable])
Tuples may be constructed in a number of ways:

  • Using a pair of parentheses to denote the empty tuple: ()
  • Using a trailing comma for a singleton tuple: a, or (a,)
  • Separating items with commas: a, b, c or (a, b, c)
  • Using the tuple() built-in: tuple() or tuple(iterable)

The constructor builds a tuple whose items are the same and in the same order as iterable’s items. iterable may be either a sequence, a container that supports iteration, or an iterator object. If iterable is already a tuple, it is returned unchanged. For example, tuple('abc') returns ('a', 'b', 'c') and tuple( [1, 2, 3] ) returns(1, 2, 3). If no argument is given, the constructor creates a new empty tuple, ().

Note that it is actually the comma which makes a tuple, not the parentheses. The parentheses are optional, except in the empty tuple case, or when they are needed to avoid syntactic ambiguity. For example, f(a, b, c)is a function call with three arguments, while f((a, b, c)) is a function call with a 3-tuple as the sole argument.

Tuples implement all of the common sequence operations.

For heterogeneous collections of data where access by name is clearer than access by index,collections.namedtuple() may be a more appropriate choice than a simple tuple object.

 

稱之為『不可變』物件呢?並非因為其『身份』 id() 不改也。而是這個『容器』不可變也!

 

舊瓶固可裝新酒,那瓶子不變也。

 

所以醞釀發酵,直把『函式』之『pass by value』── immutable ──以及『call by reference』── mutable ── 容成一爐矣!!

 

或許這只點出了『函式』語法定義規矩︰

8.6. Function definitions

A function definition defines a user-defined function object (see section The standard type hierarchy):

funcdef        ::=  [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
decorators     ::=  decorator+
decorator      ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
dotted_name    ::=  identifier ("." identifier)*
parameter_list ::=  (defparameter ",")*
                    | "*" [parameter] ("," defparameter)* ["," "**" parameter]
                    | "**" parameter
                    | defparameter [","] )
parameter      ::=  identifier [":" expression]
defparameter   ::=  parameter ["=" expression]
funcname       ::=  identifier

A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object (a wrapper around the executable code for the function). This function object contains a reference to the current global namespace as the global namespace to be used when the function is called.

The function definition does not execute the function body; this gets executed only when the function is called. [3]

A function definition may be wrapped by one or more decorator expressions. Decorator expressions are evaluated when the function is defined, in the scope that contains the function definition. The result must be a callable, which is invoked with the function object as the only argument. The returned value is bound to the function name instead of the function object. Multiple decorators are applied in nested fashion. For example, the following code

@f1(arg)
@f2
def func(): pass

is roughly equivalent to

def func(): pass
func = f1(arg)(f2(func))

except that the original function is not temporarily bound to the name func.

When one or more parameters have the form parameter = expression, the function is said to have “default parameter values.” For a parameter with a default value, the corresponding argument may be omitted from a call, in which case the parameter’s default value is substituted. If a parameter has a default value, all following parameters up until the “*” must also have a default value — this is a syntactic restriction that is not expressed by the grammar.

Default parameter values are evaluated from left to right when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function, e.g.:

def whats_on_the_telly(penguin=None):
    if penguin is None:
        penguin = []
    penguin.append("property of the zoo")
    return penguin

Function call semantics are described in more detail in section Calls. A function call always assigns values to all parameters mentioned in the parameter list, either from position arguments, from keyword arguments, or from default values. If the form “*identifier” is present, it is initialized to a tuple receiving any excess positional parameters, defaulting to the empty tuple. If the form “**identifier” is present, it is initialized to a new dictionary receiving any excess keyword arguments, defaulting to a new empty dictionary. Parameters after “*” or “*identifier” are keyword-only parameters and may only be passed used keyword arguments.

Parameters may have annotations of the form “: expression” following the parameter name. Any parameter may have an annotation even those of the form *identifier or **identifier. Functions may have “return” annotation of the form “-> expression” after the parameter list. These annotations can be any valid Python expression and are evaluated when the function definition is executed. Annotations may be evaluated in a different order than they appear in the source code. The presence of annotations does not change the semantics of a function. The annotation values are available as values of a dictionary keyed by the parameters’ names in the __annotations__attribute of the function object.

It is also possible to create anonymous functions (functions not bound to a name), for immediate use in expressions. This uses lambda expressions, described in section Lambdas. Note that the lambda expression is merely a shorthand for a simplified function definition; a function defined in a “def” statement can be passed around or assigned to another name just like a function defined by a lambda expression. The “def” form is actually more powerful since it allows the execution of multiple statements and annotations.

Programmer’s note: Functions are first-class objects. A “def” statement executed inside a function definition defines a local function that can be returned or passed around. Free variables used in the nested function can access the local variables of the function containing the def. See section Naming and binding for details.

See also

PEP 3107 – Function Annotations
The original specification for function annotations.

恐還難跨越『可呼叫』者︰

callable(object)

Return True if the object argument appears callable, False if not. If this returns true, it is still possible that a call fails, but if it is false, calling object will never succeed. Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a __call__() method.

New in version 3.2: This function was first removed in Python 3.0 and then brought back in Python 3.2.

※ 参考︰

3.3.5. Emulating callable objects

object.__call__(self[, args…])

Called when the instance is “called” as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).

 

『術語』準繩,尚未知『第一類公民』何物哩。

也許『郭沫若』說的好︰

』是『』的,書是『』的。『』『』讀『』『』,可以把『』讀『』。『』『』讀『』『』,可以把『』讀『』。

如何『』 Python ?就從『』本『派生』的『』開始。因『』故及於它『』它『』,以至於『』而已!!

□︰ 難道都不用練習的嗎?

○︰此語未免太癡!《論語》

學而』篇開宗明義講︰『』而時『』之的吧!!

比方說《潜入派生》 Dive into Python 第二章第四節

《 2.4. Everything Is an Object 》講︰

2.4.2. What’s an Object?

Everything in Python is an object, and almost everything has attributes and methods. All functions have a built-in attribute __doc__, which returns the doc string defined in the function’s source code. The sys module is an object which has (among other things) an attribute called path. And so forth.

Still, this begs the question. What is an object? Different programming languages define “object” in different ways. In some, it means that all objects must have attributes and methods; in others, it means that all objects are subclassable. In Python, the definition is looser; some objects have neither attributes nor methods (more on this in Chapter 3), and not all objects are subclassable (more on this in Chapter 5). But everything is an object in the sense that it can be assigned to a variable or passed as an argument to a function (more in this in Chapter 4).

This is so important that I’m going to repeat it in case you missed it the first few times: everything in Python is an object. Strings are objects. Lists are objects. Functions are objects. Even modules are objects.

那麼我們將如何理解『在派生中,一切皆是物件。』這句話呢?要是不深入『派生』的『語法』以及『語意』,只依靠著『語用』根本是不足以『回答』的吧!而且不同的『程式語言』,『口號』不同,『哲學』也不一樣!!Python 號稱『多典範』,『程序』為主的寫作、『物件』中心之編程,『泛函式』概念的淺嚐,……等等,也許可以這麼說︰

『派生』支持的『作法』,讓它『語法』上『方便容易』。

『派生』不支持的『行事』,也可『己選自擇』的『表現』。

因此想要掌握 Python 語言,『深思』、『細慮』以及『多實驗』或許是個好的起步。就像嘗試看看,在『派生』中,什麼是『函式』 function 的呢?

pi@raspberrypi ~ $ python3
Python 3.2.3 (default, Mar  1 2013, 11:53:50) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.

# 列出『整數』物件有的『屬性』與『方法』
>>> dir(3)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']


# 『泛函式』小試
>>> def 求值(函數,參數):
...     return 函數(參數)
... 

# 『函數』定義
>>> def f(x):
...     return x*x +2*x -1
... 

# 『函數』求值
>>> 求值(f,5)
34

# f 是『函數』物件的『標識符』
>>> f
<function f at 0x76a5cf60>

# 『函數』呼叫,是由『標識符』 f 與『參數元組』 (5) 所構成
>>> f (5)
34

# 『函數』的重要『屬性』是『可呼叫』 callable
>>> callable(f)
True

# 列出『函數』物件有的『屬性』與『方法』
>>> dir(f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

# λ 『匿名函數』
>>> 求值(lambda x:x*x + 2*x -1,5)
34

>>> lambda x:x*x + 2*x -1
<function <lambda> at 0x76a5ced0>

>>> dir(lambda x:x*x + 2*x -1)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

 

─── 豈是一句『可呼叫』 callable 了得!! ───

─── 摘自《W!O 的派生‧十日談之《七》