f <- function(x = 0) {
return(x^2)
}
body(f) # function body
## {
## return(x^2)
## }
formals(f) # pair list
## $x
## [1] 0
environment(f) # enclosing environment
## <environment: R_GlobalEnv>
sin
## function (x) .Primitive("sin")
typeof(sin)
## [1] "builtin"
typeof(`[`)
## [1] "special"
formals(sin)
## NULL
body(sin)
## NULL
environment(sin)
## NULL
f <- function(x) {
10
}
f(x = stop("This is an error")) # 因為函數執行並不需要變數x,故不會引發錯誤訊息
## [1] 10
y <- 10
g <- function(x) {
y <- 100
x + 1
}
g(x = y)
## [1] 11
g(x <- 1000)
## [1] 1001
x
## [1] 1000
y
## [1] 10
myfun <- function(x = 0, y = 0) {
sqrt(x^2 + y^2)
}
myfun(x = 5, y = 12)
## [1] 13
normalize <- function(x, m, s) {
(x - m)/s
}
set.seed(seed = 188)
d <- rnorm(n = 20, mean = 10, sd = 5)
M <- mean(x = d)
M
## [1] 9.517236
S <- sd(x = d)
S
## [1] 5.292199
# fix(normalize)
normalize <- function(x = x, m = mean(x = x), s = sd(x = x)) {
(x - m)/s
}
d[length(d)] <- NA
normalize(x = d)
## [1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
normalize <- function(x = x, m = mean(x = x, na.rm = na.rm), s = sd(x = x, na.rm = na.rm), na.rm = FALSE) {
(x - m)/s
}
normalize(x = d, na.rm = TRUE)
## [1] -1.44073405 0.02090840 -1.90504451 -0.16368790 0.10973385 -1.08329130
## [7] 0.39229251 -0.12139770 0.58228453 -0.88490550 0.41161626 0.85427282
## [13] -0.04821785 -0.64634636 1.32801068 -0.57923463 -0.21985236 2.22903647
## [19] 1.16455665 NA
normalize <- function(x = x, m = mean(x = x, ...), s = sd(x = x, ...), ...) {
(x - m)/s
}
normalize(x = d, na.rm = TRUE)
## [1] -1.44073405 0.02090840 -1.90504451 -0.16368790 0.10973385 -1.08329130
## [7] 0.39229251 -0.12139770 0.58228453 -0.88490550 0.41161626 0.85427282
## [13] -0.04821785 -0.64634636 1.32801068 -0.57923463 -0.21985236 2.22903647
## [19] 1.16455665 NA
normalize <- function(x = x, m = mean(x = x, trim = trim, ...),
s = sd(x = x, ...), trim = 0, ...) {
(x - m)/s
}
normalize(x = d, trim = 0, na.rm = TRUE)
## [1] -1.44073405 0.02090840 -1.90504451 -0.16368790 0.10973385 -1.08329130
## [7] 0.39229251 -0.12139770 0.58228453 -0.88490550 0.41161626 0.85427282
## [13] -0.04821785 -0.64634636 1.32801068 -0.57923463 -0.21985236 2.22903647
## [19] 1.16455665 NA
normalize(x = d, trim = 0.2, na.rm = TRUE)
## [1] -1.41823144 0.04341101 -1.88254190 -0.14118529 0.13223646 -1.06078869
## [7] 0.41479512 -0.09889509 0.60478714 -0.86240289 0.43411887 0.87677543
## [13] -0.02571524 -0.62384375 1.35051329 -0.55673202 -0.19734975 2.25153908
## [19] 1.18705926 NA
h <- function(x = ls()) {
a <- 1
x
}
h()
## [1] "a" "x"
h(x = ls())
## [1] "d" "f" "g" "h" "M" "myfun"
## [7] "normalize" "S" "x" "y"
addTheLog <- function(first, second) {
first + log(second)
}
addTheLog(first = 1, second = exp(4))
## [1] 5
addTheLog(second = exp(4), first = 1)
## [1] 5
addTheLog(f = 1, s = exp(4))
## [1] 5
addTheLog(s = exp(4), f = 1)
## [1] 5
addTheLog(1, exp(4))
## [1] 5
addTheLog(exp(4), 1)
## [1] 54.59815
mean(1:10, n = T)
## [1] 5.5
mean(1:10, , FALSE)
## [1] 5.5
mean(1:10, 0.05)
## [1] 5.5
mean(, TRUE, x = c(1:10, NA))
## [1] 5.5
常搭配lapply函數結果使用。
args <- list(1:10, na.rm = TRUE) # 參數list
do.call(what = mean, args = args)
## [1] 5.5
# Equivalent to
mean(1:10, na.rm = TRUE)
## [1] 5.5
j01 <- function(x) {
if (x < 10) {
0
} else {
10
}
}
j01(5)
## [1] 0
j01(20)
## [1] 10
j02 <- function(x) {
if (x < 10) {
return(0)
} else {
return(10)
}
}
k01 <- function() 1
k01()
## [1] 1
a <- k01()
a
## [1] 1
k02 <- function() invisible(1)
k02()
b <- k02()
b
## [1] 1
withVisible(k02())
## $value
## [1] 1
##
## $visible
## [1] FALSE
def f(x, y):
x + y
f(1, 2)
ans = f(1, 2)
ans
type(ans)
## <class 'NoneType'>
def fact(n):
"""Return the factorial of the given number.""" # docstring: 『文件字串』,用來說明這個函數的用途
r = 1
while n > 0:
r = r *n
n = n - 1
return r # 回傳值為r
type(fact)
## <class 'function'>
x = fact(n = 4)
x
## 24
help(fact) # 查詢函數的help說明
## Help on function fact in module __main__:
##
## fact(n)
## Return the factorial of the given number.
fact.__doc__ # 回傳docstring的內容,亦為函數的屬性
## 'Return the factorial of the given number.'
def func(a):
b = 'spam'
return b * a
func(3)
## 'spamspamspam'
func.__name__
## 'func'
dir(func)
## ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
func.count = 0
func.count += 1
func.count
## 1
dir(func)
## ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count']
def power(x, y): # positional parameter
r = 1
while y > 0:
r = r * x
y = y - 1
return r
power(3, 4) # positional argument
## 81
# power(3)
# TypeError: power() missing 1 required positional argument: 'y'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
定義函數時,你可以對參數設定預設值(default value)。
def power(x, y = 2): # y設定預設值
r = 1
while y > 0:
r = r * x
y = y - 1
return r
power(3, 4)
## 81
power(3)
## 9
# def func(x = 2, y):
# pass
#
# 錯誤: non-default argument follows default argument (<string>, line 1)
power(2, 3)
## 8
power(3, 2)
## 9
power(y = 2, x = 3)
## 9
請看下面例子,並注意錯誤訊息,與R語言有很大的不同 (請思考,如果是R,下面的函數呼叫會發生錯誤嗎?)
# power(2, x = 3)
# TypeError: power() got multiple values for argument 'x'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
power(3, y = 2) # 滿足『位置引數』在前,『指名引數』在後
# 注意下面例子結果與錯誤訊息
# power(x = 3, 2) # 違反『位置引數』在前,『指名引數』在後
# 錯誤: positional argument follows keyword argument (<string>, line 2)
## 9
def f(*x):
print(x)
f(1, 2, 3, 4)
# f(x =1, y = 2, p = 3, q = 4)
# TypeError: f() got an unexpected keyword argument 'x'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
## (1, 2, 3, 4)
def g(**x):
print(x)
g(x =1, y = 2, p = 3, q = 4)
# g(1, 2, 3, 4)
# TypeError: g() takes 0 positional arguments but 4 were given
#
# Detailed traceback:
# File "<string>", line 1, in <module>
## {'x': 1, 'y': 2, 'p': 3, 'q': 4}
def maximum(*numbers): # 帶有*的參數
if len(numbers) == 0:
return None
else:
maxnum = numbers[0]
for n in numbers[1:]:
if n > maxnum:
maxnum = n
return maxnum
maximum(1, 5, 9, -2, 2)
## 9
def example_fun(x, y, **other):
print("x: {0}, y: {1}, keys in 'other': {2}".format(x,
y, list(other.keys())))
other_total = 0
for k in other.keys():
other_total = other_total + other[k]
print("The total of values in 'other' is {0}".format(other_total))
example_fun(2, y="1", foo=3, bar=4)
## x: 2, y: 1, keys in 'other': ['foo', 'bar']
## The total of values in 'other' is 7
def f1(x, y, *args):
print(x, y, args, sep = '\n')
f1(1, 2, 3)
## 1
## 2
## (3,)
f1(1, 2, 3, 4, 5)
## 1
## 2
## (3, 4, 5)
def f2(x, y, **kwargs):
print(x, y, kwargs, sep = '\n')
f2(1, 2, p = 3)
## 1
## 2
## {'p': 3}
f2(1, 2, p = 3, q = 4, r = 5)
# f2(1, 2, p = 3, q = 4, r = 5, x = 100)
# TypeError: f2() got multiple values for argument 'x'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
## 1
## 2
## {'p': 3, 'q': 4, 'r': 5}
def func(a, b, c, d): print(a, b, c, d)
func(*(1, 2, 3,4))
## 1 2 3 4
func(**{'a': 1, 'd': 2, 'b': 3, 'c': 4})
## 1 3 4 2
func(1, 2, **{'c':3, 'd': 4})
## 1 2 3 4
func(1, c = 3, *(2,), **{'d': 4})
## 1 2 3 4
func(1, *(2,), c = 3, **{'d': 4})
## 1 2 3 4
# func(1, b = 3, *(2,), **{'d': 4})
# TypeError: func() got multiple values for argument 'b'
def myfun(x, y = 0, *args, **kwargs):
print(x, y, args, kwargs, sep = '\n')
# myfun(1, y = 2, 3, 4, 5, p = 100, q = 200)
# 錯誤: positional argument follows keyword argument (<string>, line 5)
# myfun(1, y = 2, *(3, 4, 5), p = 100, q = 200)
# TypeError: myfun() got multiple values for argument 'y'
myfun(1, 2, 3, 4, 5, p = 100, q = 200)
## 1
## 2
## (3, 4, 5)
## {'p': 100, 'q': 200}
myfun(1, *(3, 4, 5), p = 100, q = 200)
## 1
## 3
## (4, 5)
## {'p': 100, 'q': 200}
def f(n, list1, list2):
list1.append(3)
list2 = [4, 5, 6]
n = n + 1
x = 5
y = [1, 2]
z = [4, 5]
f(x, y, z)
x, y, z
## (5, [1, 2, 3], [4, 5])
def f(lst):
lst = lst[:]
lst.append(3)
x = [1, 2]
f(x)
x
## [1, 2]
def kwonly(a, *args, c): # c為keyword-only參數
print(a, args, c)
kwonly(1, 2, c = 3)
## 1 (2,) 3
kwonly(1, c = 3)
## 1 () 3
# kwonly(1, 2, 3)
# TypeError: kwonly() missing 1 required keyword-only argument: 'c'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
def kwonly(a, *, b, c):
print(a, b, c)
kwonly(1, c = 3, b = 2)
## 1 2 3
kwonly(c= 3, b = 2, a = 1)
## 1 2 3
# kwonly(1, 2, 3)
# TypeError: kwonly() takes 1 positional argument but 3 were given
#
# Detailed traceback:
# File "<string>", line 1, in <module>
# kwonly(1)
# TypeError: kwonly() missing 2 required keyword-only arguments: 'b' and 'c'
#
# Detailed traceback:
# File "<string>", line 1, in <module>
def kwonly(a, *, b = 0, c = 0):
print(a, b, c)
kwonly(1)
## 1 0 0
kwonly(1, c = 100)
## 1 0 100
# def kwonly(a, **args, b, c):
# pass
#
# 錯誤: invalid syntax (<string>, line 1)
# def kwonly(a, **, b, c):
# pass
#
# 錯誤: invalid syntax (<string>, line 6)
# def f(a, *b, **d, c = 6): print(a, b, c, d)
# 錯誤: invalid syntax (<string>, line 1)
def f(a, *b, c = 10, **d): print(a, b, c, d, sep= '\n')
f(1, 2, 3, x = 4, y = 5)
## 1
## (2, 3)
## 10
## {'x': 4, 'y': 5}
f(1, 2, 3, x = 4, y = 5, c = 6)
## 1
## (2, 3)
## 6
## {'x': 4, 'y': 5}
def f(a, c = 6, *b, **d):
print(a, b, c, d)
f(1, 2, 3, 4)
## 1 (3, 4) 2 {}
def data_append(v, lst = []): # lst參數預設值為可變的空list
lst.append(v)
return lst
data_append(1)
## [1]
data_append(2) # 注意執行的結果,是否為[2]?
## [1, 2]
上述例子,lst參數在函數定義時參照可變之list物件,此物件並不會在函數結束呼叫後而刪除進行垃圾回收,且一直保留。故第一次的執行結果會影響第二次的執行結果。
解決方法如下:
def data_append(v, lst = None):
if lst is None:
lst = []
lst.append(v)
return lst
data_append(1)
## [1]
data_append(2) # 不會受上一次執行結果的影響了
## [2]
def data_append(v, lst = None):
if lst is None:
lst = []
lst.append(v)
return lst
lt = [100, 200, 300]
lt
## [100, 200, 300]
data_append(1, lst = lt)
## [100, 200, 300, 1]
lt # 外部的lt也被改變了嗎??
# data_append()函數要怎麼修正??
## [100, 200, 300, 1]