Partial

_.partial

_.partial을 통해 인자를 부분 적용해둔 함수를 만들 수 있습니다.

1
2
3
4
5
6
def add(a, b):
return a + b
add10 = _.partial(add, 10)
result = add10(5)
print(result) # 15

_

_ == _.partial입니다. _.partial_로 짧게 줄여서 사용할 수 있습니다.

1
2
3
4
5
6
7
def add(a, b):
return a + b
add10 = _(add, 10)
result = add10(5)
print(result)
# 15

_.partial 혹은 _를 실행하면서 인자 자리에 자기 자신인 _를 넘기면 부분 적용할 인자를 건너띌 수 있습니다. _를 이용하면 원하는 곳에만 인자를 부분 적용해둘 수 있습니다. _가 있는 자리는 이후 실행시 채워집니다.

1
2
3
4
5
6
7
def sub(a, b):
return a - b
sub10 = _.partial(sub, _, 10)
result = sub10(20)
print(result)
# 10

___

부분 적용의 새로운 구분자인 ___를 활용하면 중간 지점에 인자가 가변적으로 적용되도록 비워둘 수 있습니다. 이것을 이용해 맨 오른쪽 인자나 맨 오른쪽에서 두 번째에만 인자를 적용해두는 것도 가능합니다. ___를 기준으로 왼편의 인자들을 왼쪽부터 적용하고 오른편의 인자들을 오른쪽부터 적용할 준비를 해둔 함수를 리턴합니다. 부분 적용된 함수를 나중에 실행하면 그때 받은 인자들로 왼쪽과 오른쪽을 먼저 채운 후, 남은 인자들로 가운데 ___ 자리를 채웁니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pc = _.partial(print, ___, 2, 3)
pc(1)
# 결과: 1 2 3
# ___ 자리에 1이 들어가고 2, 3은 맨 오른쪽에 들어갑니다.
pc(1, 4, 5, 6)
# 결과: 1 4 5 6 2 3
# ___ 자리에 1, 4, 5, 6이 들어가고 2, 3은 맨 오른쪽에 들어갑니다.
pc = _.partial(print, _, 2, ___, 6)
pc(1, 3, 4, 5)
# 결과: 1 2 3 4 5 6
# _에 1이 들어가고 2를 넘어가고 ___ 자리에 3, 4, 5가 채워지고 6이 맨 오른쪽에 들어갑니다.
pc(1, 3, 4, 5, 7, 8, 9)
# 결과: 1 2 3 4 5 7 8 9 6
# _에 1이 들어가고 2를 넘어가고 ___ 자리에 3, 4, 5, 7, 8, 9가 채워지고 6이 맨 오른쪽에 들어갑니다.
pc = _.partial(print, _, 2, ___, 5, _, 7)
pc(1)
# 결과: 1 2 5 None 7
# _ 자리에 1이 들어가고 2와 5사이는 유동적이므로 모이고 5가 들어간 후 _가 None로 대체 되고 7이 들어갑니다.
pc(1, 3, 4)
# 결과: 1 2 3 5 4 7
# _ 자리에 1이 들어가고 2와 5사이에 3이 들어가고 _ 를 4로 채운 후 7이 들어갑니다.
# 왼쪽의 _ 들이 우선 순위가 제일 높고 ___ 보다 오른쪽의 _ 들이 우선순위가 높습니다.
pc(1, 3, 4, 6, 8)
# 결과: 1 2 3 4 6 5 8 7
# _ 자리에 1이 들어가고 2와 5사이에 3, 4, 6이 들어가고 _ 를 8로 채운 후 7이 들어갑니다.

Pipe

__

_.pipe

_.pipe는 함수들을 모아서 하나의 함수로 합성하는 함수입니다. 왼쪽에서 오른쪽으로 실행됩니다.

1
2
3
4
5
6
7
8
9
10
def sum(a, b):
return a + b
def square(a):
return a * a
f1 = _.pipe(sum, square, square)
result = f1(1, 2)
print(result)
# 81

_.go

_.go는 파이프라인의 즉시 실행 버전입니다. 첫 번째 인자로 받은 값을 두 번째 인자로 받은 함수에게 넘겨주고 두 번째 인자로 받은 함수의 결과는 세 번째 함수에게 넘겨주는 것을 반복하다가 마지막 함수의 결과를 리턴해줍니다.

1
2
3
4
5
6
7
_.go(10, # 첫 번째 함수에서 사용할 인자
lambda a: a * 10, # 연속 실행할 함수 1
# 100
lambda a: a - 50, # 연속 실행할 함수 2
# 50
lambda a: a + 10) # 연속 실행할 함수 3
# 60

_.mr

Partial.py의 파이프라인 함수들은 Multiple Results를 지원합니다. _.mr 함수를 함께 사용하면 다음 함수에게 2개 이상의 인자들을 전달할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
_.go(10, # 첫 번째 함수에서 사용할 인자
lambda a: _.mr(a * 10, 50), # 두 개의 값을 리턴
lambda a, b: a - b, # 두 개의 인자 받기
lambda a: a + 10,
print)
# 60
_.go(_.mr(2, 3),
lambda a, b: a + b, # 2 + 3
lambda a: a * a,
print)
# 25

_.tap

_.tap은 받아둔 함수들을 모두 실행한 후 처음 받은 인자를 동일하게 리턴하는 파이프라인 함수입니다.

1
2
3
4
5
_.go(10,
_.tap(
lambda a: a * a,
print), # 100
print) # 10

Collections

_.each

_.each(list, iteratee) 리스트를 끝까지 순회하며 함수를 실행합니다.

1
2
3
4
_.each([1,2,3], print)
# print 함수가 각 번호에 맞춰 실행됩니다.
_.each({'one': 1, 'two': 2, 'three': 3}, print)
# print 함수가 각 번호 값에 맞춰 실행됩니다.

_.map

_.map(list, iteratee) 리스트를 순회하며 주어진 함수로 새로운 배열을 생성합니다.

1
2
3
4
5
6
_.map([1,2,3], lambda num, *r: num * 3)
# [3, 6, 9]
_.map({'one': 1, 'two': 2, 'three': 3}, lambda num, key, *r: num * 3)
# [3, 6, 9]
_.map([[1, 2], [3, 4]], _.first)
# [1, 3]

_.reduce

_.reduce(list, iteratee, [memo]) inject 혹은 foldl라고 불리는 이 함수는 리스트를 순회하며 하나의 값을 추출합니다. memo는 옵션값이며 추출될 값의 초기값이 됩니다.

1
2
sum = _.reduce([1, 2, 3], lambda memo, num, *r: memo + num, 0)
print(sum) # 6

_.reduceRight

_.reduceRight(list, iteratee, [memo]) _.reduce와 반대 방향으로 순회하며 하나의 값을 추출합니다.

1
2
3
list = [[0, 1], [2, 3], [4, 5]]
flat = _.reduceRight(list, lambda a, b, *r: a + b, [])
print(flat) # [4, 5, 2, 3, 0, 1]

_.find

_.find(list, predicate) 리스트의 내부 값을 관찰하여 predicate의 결과가 참인 값을 반환합니다.

1
2
even = _.find([1, 2, 3, 4, 5, 6], lambda num, *r: num % 2 == 0)
print(even) # 2

_.filter

_.filter(list, predicate) 리스트의 내부 값을 관찰하여 predicate의 결과가 참인 값들을 배열로 반환합니다.

1
2
evens = _.filter([1, 2, 3, 4, 5, 6], lambda num, *r: num % 2 == 0)
print(evens) # [2, 4, 6]

_.where

_.where(list, properties) 리스트의 내부 값을 관찰하여 프로퍼티를 포함하고 있는 객체들을 배열로 반환합니다.

1
2
_.where(listOfPlays, {'author': 'Shakespeare', 'year': 1611})
# [{'title': 'Cymbeline', 'author': 'Shakespeare', 'year': 1611}, {'title': 'The Tempest', 'author': 'Shakespeare', 'year': 1611}]

_.findWhere

_.findWhere(list, properties) 리스트의 내부 값을 관찰하여 프로퍼티를 포함하고 있는 첫번째 객체를 반환합니다.

1
2
3
4
5
6
7
8
9
_.findWhere(publicServicePulitzers, {'newsroom': 'The New York Times'})
/*
{
'year': 1918, 'newsroom': 'The New York Times',
'reason': 'For its public service in publishing in full so many official reports,
documents and speeches by European statesmen relating to the progress and
conduct of the war.'
}
*/

_.reject

_.reject(list, predicate) 리스트를 순회하며 predicate의 결과가 참인 값들을 제외한 배열을 반환합니다.

1
2
odds = _.reject([1, 2, 3, 4, 5, 6], lambda num, *r: num % 2 == 0)
print(odds) # [1, 3, 5]

_.every

_.every(list, [predicate]) 리스트의 모든 값이 참에 해당하는 값인지 판별합니다. 거짓 값을 발견하면 순회를 멈춥니다.

1
2
_.every([2, 4, 5], lambda num, *r: num % 2 == 0)
# False

_.some

_.some(list, [predicate]) 리스트의 값 중 참에 해당하는 값이 하나라도 있다면 참을 반환합니다. 참 값을 발견하면 순회를 멈춥니다.

1
2
_.some([None, 0, 'yes', False])
# True

_.contains

_.contains(list, value, [fromIndex]) 리스트의 값이 value를 포함한다면 참을 반환합니다.

1
2
_.contains([1, 2, 3], 3)
# True

_.invoke

_.invoke(list, methodName, *arguments) 리스트의 각 값이 가지고 있는 메소드를 실행합니다.

1
2
_.invoke(['foo', 'bar'], 'upper')
# ['FOO', 'BAR']

_.pluck

_.pluck(list, propertyName) 프로퍼티의 값만을 추출합니다.

1
2
3
stooges = [{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}, {'name': 'curly', 'age': 60}]
_.pluck(stooges, 'name')
# ['moe', 'larry', 'curly']

_.max

_.max(list, [iteratee]) 리스트의 값 중 최대값을 반환합니다. 만약 iteratee 함수를 전달하면 해당 함수가 최대값이 될 기준을 정합니다.

1
2
3
stooges = [{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}, {'name': 'curly', 'age': 60}]
_.max(stooges, lambda stooge, *r: stooge['age'])
# {'name': 'curly', 'age': 60}

_.min

_.min(list, [iteratee]) 리스트의 값 중 최소값을 반환합니다. 만약 iteratee 함수를 전달하면 해당 함수가 최소값이 될 기준을 정합니다.

1
2
3
numbers = [10, 5, 100, 2, 1000]
_.min(numbers)
# 2

_.sortBy

_.sortBy(list, iteratee) 리스트의 값들을 정렬합니다.

1
2
3
4
5
6
_.sortBy([1, 2, 3, 4, 5, 6], lambda num, *r: math.sin(num))
# [5, 4, 6, 3, 1, 2]
stooges = [{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}, {'name': 'curly', 'age': 60}]
_.sortBy(stooges, 'name')
# [{'name': 'curly', 'age': 60}, {'name': 'larry', 'age': 50}, {'name': 'moe', 'age': 40}]

_.groupBy

_.groupBy(list, iteratee) 리스트의 값들을 iteratee를 통해 특정 집합으로 분류합니다.

1
2
3
4
5
_.groupBy([1.3, 2.1, 2.4], lambda num, *r: math.floor(num))
# {1: [1.3], 2: [2.1, 2.4]}
_.groupBy(['one', 'two', 'three'], lambda str, *r: len(str))
# {3: ['one', 'two'], 5: ['three']}

_.indexBy

_.indexBy(list, iteratee) 특정 리스트의 값을 인덱스 값으로 반영한 객체를 반환합니다. _.groupBy와 비슷하지만 알고 있는 키의 값이 유니크 할 때 사용합니다.

1
2
3
4
5
6
7
8
9
stooges = [{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}, {'name': 'curly', 'age': 60}]
_.indexBy(stooges, 'age')
/*
{
'40': {'name': 'moe', 'age': 40},
'50': {'name': 'larry', 'age': 50},
'60': {'name': 'curly', 'age': 60}
}
*/

_.countBy

_.countBy(list, iteratee) 리스트의 값들을 iteratee를 통해 분류된 값의 개수 정리한 객체를 반환합니다.

1
2
_.countBy([1, 2, 3, 4, 5], lambda num, *r: 'even' if num % 2 is 0 else 'odd')
# {'odd': 3, 'even': 2}

_.shuffle

_.shuffle(list) 리스트의 값의 순서를 섞은 사본을 반환합니다.

1
2
_.shuffle([1, 2, 3, 4, 5, 6])
# [4, 1, 6, 3, 5, 2]

_.sample

_.sample(list, [n]) 리스트에서 임의의 샘플을 반환합니다. 옵션 값인 n값을 통해 샘플의 수를 정할 수 있습니다.

1
2
3
4
5
_.sample([1, 2, 3, 4, 5, 6])
# 4
_.sample([1, 2, 3, 4, 5, 6], 3)
# [1, 6, 2]

_.size

_.size(list) 리스트에 있는 값의 개수를 반환합니다.

1
2
_.size({'one': 1, 'two': 2, 'three': 3})
# 3

_.partition

_.partition(array, predicate) 하나의 배열을 predicate를 만족하는 배열과 그렇지 않은 배열로 나눕니다.

1
2
_.partition([0, 1, 2, 3, 4, 5], lambda num, *r: num % 2)
# [[1, 3, 5], [0, 2, 4]]

Array

_.first

_.first(array, [n]) 배열의 첫번째 요소를 반환합니다. n으로 몇개까지 반환할지 결정할 수 있습니다.

1
_.first([5, 4, 3, 2, 1]) # 5

_.initial

_.initial(array, [n]) 배열의 마지막 요소만 제외한 배열을 반환합니다.

1
_.initial([5, 4, 3, 2, 1]) # [5, 4, 3, 2]

_.last

_.last(array, [n]) 배열의 마지막 요소를 반환합니다. n으로 몇개까지 반환할지 결정할 수 있습니다.

1
_.last([5, 4, 3, 2, 1]) # 1

_.rest

_.rest(array, [n]) 배열의 첫번째 요소만 제외한 배열을 반환합니다.

1
_.rest([5, 4, 3, 2, 1]) # [4, 3, 2, 1]

_.compact

_.compact(array) 배열의 모든 거짓 값을 제거한 배열의 사본을 반환합니다.

1
_.compact([0, 1, False, 2, '', 3]) # [1, 2, 3]

_.flatten

_.flatten(array, [noDeep]) 중첩 배열(nested array)을 풀어냅니다. 만약에 noDeep을 전달하면 배열을 한단계만 풉니다.

1
2
3
4
5
_.flatten([1, [2], [3, [[4]]]])
# [1, 2, 3, 4]
_.flatten([1, [2], [3, [[4]]]], True)
# [1, 2, 3, [[4]]]

_.without

_.without(array, *values) values와 같은 값이 제거된 배열의 사본을 반환합니다.

1
2
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1)
# [2, 3, 4]

_.union

_.union(*arrays) 배열들의 값을 확인하여 하나의 합집합 배열을 만듭니다.

1
2
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1])
# [1, 2, 3, 101, 10]

_.intersection

_.intersection(*arrays) 배열들의 값을 확인하여 하나의 교집합 배열을 만듭니다.

1
2
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1])
# [1, 2]

_.difference

_.difference(array, *others) 첫번째 배열과 비교하여 하나의 차집합 배열을 만듭니다.

1
2
_.difference([1, 2, 3, 4, 5], [5, 2, 10])
# [1, 3, 4]

_.uniq

_.uniq(array, [iteratee]) 배열에서 중복을 제거된 상태의 배열을 만듭니다.

1
2
_.uniq([1, 2, 1, 4, 1, 3])
# [1, 2, 4, 3]

_.zip

_.zip(*arrays) 배열들의 값 중 인덱스가 동일한 값끼리 묶은 다중 배열을 만듭니다.

1
2
_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [True, False, False])
# [['moe', 30, True], ['larry', 40, False], ['curly', 50, False]]

_.unzip

_.unzip(array) 인자로 전달된 다중 배열에서 인덱스가 동일한 값끼리 재배열한 다중 배열을 만듭니다.

1
2
_.unzip([['moe', 30, True], ['larry', 40, False], ['curly', 50, False]])
# [['moe', 'larry', 'curly'], [30, 40, 50], [True, False, False]]

_.object

_.object(list, [values]) 배열을 객체로 만듭니다. 키가 될 배열과 값이 될 배열을 인자로 함께 전달하거나 하나의 배열에 키와 값을 쌍으로 가진 복수의 배열을 전달할 수 있습니다.

1
2
3
4
5
_.object(['moe', 'larry', 'curly'], [30, 40, 50])
# {'moe': 30, 'larry': 40, 'curly': 50}
_.object([['moe', 30], ['larry', 40], ['curly', 50]])
# {'moe': 30, 'larry': 40, 'curly': 50}

_.indexOf

_.indexOf(array, value, [isSorted]) 배열을 순서대로 탐색해 value와 일치하는 값의 인덱스를 찾습니다. 일치하는 값을 찾을 수 없다면 -1을 반환합니다. 정렬된 배열이라면 isSortedTrue를 전달함으로써 보다 빠른 검색이 가능해집니다. 혹은 인덱스 값을 전달해서 탐색을 시작할 위치를 정할 수도 있습니다.

1
2
_.indexOf([1, 2, 3], 2)
# 1

_.lastIndexOf

_.lastIndexOf(array, value, [fromIndex]) 배열의 끝에서부터 탐색해 value와 일치하는 값의 인덱스를 찾습니다. 찾을 수 없다면 -1을 반환합니다. fromIndex값으로 탐색을 시작할 위치 정할 수 있습니다.

1
2
_.lastIndexOf([1, 2, 3, 1, 2, 3], 2)
# 4

_.sortedIndex

_.sortedIndex(list, value, [iteratee]) 리스트를 탐색하며 value가 삽입되었을 때 리스트의 정렬된 상태를 유지할 수 있는 위치의 인덱스를 찾습니다.

1
2
3
4
5
6
_.sortedIndex([10, 20, 30, 40, 50], 35)
# 3
stooges = [{'name': 'moe', 'age': 40}, {'name': 'curly', 'age': 60}]
_.sortedIndex(stooges, {'name': 'larry', 'age': 50}, 'age')
# 1

_.findIndex

_.findIndex(array, predicate) _.indexOf와 같은 일을 하지만 predicate가 참을 반환하는 값의 인덱스를 찾습니다.

1
2
3
4
_.findIndex([4, 6, 8, 12], isPrime)
# -1
_.findIndex([4, 6, 7, 12], isPrime)
# 2

_.findLastIndex

_.findLastIndex(array, predicate) _.findIndex처럼 predicate가 참을 반환하는 값의 인덱스를 찾지만, 배열의 역순으로 탐색합니다.

1
2
3
4
5
6
users = [{'id': 1, 'name': 'Bob', 'last': 'Brown'},
{'id': 2, 'name': 'Ted', 'last': 'White'},
{'id': 3, 'name': 'Frank', 'last': 'James'},
{'id': 4, 'name': 'Ted', 'last': 'Jones'}]
_.findLastIndex(users, {'name': 'Ted'})
# 3

_.range

_.range([start], stop, [step]) 범위를 정해 정수로 구성된 배열을 만듭니다. 값을 하나만 전달하면 0부터 전달된 값 이전까지가 범위가 됩니다.

1
2
3
4
5
6
7
8
9
10
_.range(10)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5)
# [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1)
# [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0)
# []

Object

_.keys

_.keys(object) 객체가 가진 프로퍼티의 이름인 키 값들을 모아 배열을 만듭니다.

1
2
_.keys({'one': 1, 'two': 2, 'three': 3})
# ['one', 'two', 'three']

_.values

_.values(object) 객체가 가진 프로퍼티의 값을 모아 배열을 만듭니다.

1
2
_.values({'one': 1, 'two': 2, 'three': 3})
# [1, 2, 3]

_.mapObject

_.mapObject(object, iteratee) _.map과 유사하지만 객체를 만들어줍니다. 객채를 순회하며 각 프로퍼티의 값을 변경합니다.

1
2
_.mapObject({'start': 5, 'end': 12}, lambda val, key, *r: val + 5)
# {start: 10, end: 17}

_.pairs

_.pairs(object) 객체를 [key, value]의 형태의 배열들을 가진 다중 배열로 변환합니다.

1
2
_.pairs({'one': 1, 'two': 2, 'three': 3})
# [['one', 1], ['two', 2], ['three', 3]]

_.invert

_.invert(object) 객체의 프로퍼티 값과 키를 거꾸로 만들어줍니다. 값은 키로 키는 값이 됩니다. 이때 모든 값은 유니크하고 문자열로 나타낼 수 있어야합니다.

1
2
_.invert({'Moe': 'Moses', 'Larry': 'Louis', 'Curly': 'Jerome'})
# {'Moses': 'Moe', 'Louis': 'Larry', 'Jerome': 'Curly'}

_.findKey

_.findKey(object, predicate) 객체를 위한 _.findIndex입니다. predicate가 참을 반환하는 프로퍼티의 이름인 키를 반환합니다.

1
2
3
list = {'Moe': 'Moses', 'Larry': 'Louis', 'Curly': 'Jerome'}
_.findKey(list, lambda val, *r: val is 'Louis')
# 'Larry'

_.extend

_.extend(destination, *sources) sources에 해당하는 객체들의 프로퍼티를 얕게 복사해서 destination에 해당하는 객체에 붙여 객체를 확장합니다.

1
2
_.extend({'name': 'moe'}, {'age': 50})
# {name: 'moe', age: 50}

_.pick

_.pick(object, *keys) 객체의 프로퍼티 중에서 키가 일치하는 프로퍼티를 뽑은 새로운 객체를 반환합니다.

1
2
3
4
_.pick({'name': 'moe', 'age': 50, 'userid': 'moe1'}, 'name', 'age')
# {'name': 'moe', 'age': 50}
_.pick({'name': 'moe', 'age': 50, 'userid': 'moe1'}, lambda val, *r: _.isNumber(val))
# {'age': 50}

_.omit

_.omit(object, *keys) 객체의 프로퍼티 중에서 키가 일치하는 프로퍼티를 빼낸 새로운 객체를 반환합니다.

1
2
3
4
_.omit({'name': 'moe', 'age': 50, 'userid': 'moe1'}, 'userid')
# {'name': 'moe', 'age': 50}
_.omit({'name': 'moe', 'age': 50, 'userid': 'moe1'}, lambda val, *r: _.isNumber(val))
# {'name': 'moe', 'userid': 'moe1'}

_.defaults

_.defaults(object, *defaults) 객체의 프로퍼티 중 값이 None인 프로퍼티의 값을 defaults객체의 값으로 채웁니다.

1
2
3
iceCream = {'flavor': 'chocolate'}
_.defaults(iceCream, {'flavor': 'vanilla', 'sprinkles': 'lots'})
# {'flavor': 'chocolate', 'sprinkles': 'lots'}

_.clone

_.clone(object) 얕은 복사로 객체를 복제합니다. 중첩 객체의 경우에는 복제하지 않고 참조합니다.

1
2
_.clone({'name': 'moe'})
# {'name': 'moe'}

_.has

_.has(object, key) 객체에 특정 키가 존재하는지 확인합니다.

1
2
_.has({'a': '1', 'b': 2, 'c': 3}, 'b')
# True

_.isEqual

_.isEqual(object, other) 두 객체의 값을 비교해 같은지 확인합니다.

1
2
3
4
5
6
stooge = {'name': 'moe', 'luckyNumbers': [13, 27, 34]}
clone = {'name': 'moe', 'luckyNumbers': [13, 27, 34]}
stooge is clone
# False
_.isEqual(stooge, clone)
# True

_.isMatch

_.isMatch(object, properties) 두 객체를 비교해 일치하는 프로퍼티가 있는지 확인합니다.

1
2
3
stooge = {'name': 'moe', 'age': 32}
_.isMatch(stooge, {'age': 32})
# True

_.isEmpty

_.isEmpty(object) 객체가 비어있는지 확인합니다.

1
2
3
4
_.isEmpty([1, 2, 3])
# False
_.isEmpty({})
# True

_.isList

_.isList(object) 객체가 배열인지 확인합니다.

1
2
3
4
_.isList((1, 2, 3))
# False
_.isList([1, 2, 3])
# True

_.isDict

_.isDict(value) 값이 딕셔너리인지 확인합니다.

1
2
3
4
_.isDict({})
# True
_.isDict(1)
# False

_.isFunction

_.isFunction 객체가 함수인지 확인합니다.

1
2
_.isFunction(print)
# True

_.isString

_.isString(object) 객체가 문자열인지 확인합니다.

1
2
_.isString('marpple')
# True

_.isNumber

_.isNumber(object) 객체가 숫자인지 확인합니다.

1
2
_.isNumber(8.4 * 5)
# True

Function

_.memoize

_.memoize(function, [hashFunction]) 함수의 리턴 값을 저장하여, 동일한 인자가 들어올 때 저장 값을 리턴합니다

1
2
3
4
5
6
7
8
9
10
mult5 = _.memoize(lambda a, *r: a * 5)
print( mult5(1) )
# 본체 실행 1
# 5
print( mult5(2) )
# 본체 실행 2
# 10
print( mult5(1) )
# 캐시로 결과 바로 리턴 1
# 5

_.delay

_.delay(function, wait, *arguments) 정해진 시간(wait) 후에 함수가 호출 됩니다. 호출 될 함수의 인자를 옵션으로 받을 수 있습니다

1
2
_.delay(print, 1000, 'print later')
# 1초 후에 'alert later' 알림 메세지가 나타납니다.

defer

_.defer(function, *arguments) setTimeout 0과 같은 효과입니다. 콜 스택이 다 비워진 후에 함수가 호출 됩니다.

1
2
3
_.defer(lambda *r: print('deferred'))
print('first')
# 'first' 후에 'deferred'가 출력됩니다.

_.once

_.once(function) 함수가 한 번만 호출 됩니다. 그 이후의 호출은 효력이 없습니다.

1
2
3
4
5
oneTime = _.once(print)
oneTime('only one time')
# 'only one time'
oneTime('Hello, world!')
# 함수가 실행되지 않습니다.

_.after

_.after(count, function) 지정한 횟수만큼 호출 후에 함수가 호출 됩니다. 그 이후로는 호출 할때마다 함수가 호출 됩니다.

1
2
3
renderNotes = _.after(len(notes), render)
_.each(notes, _.pipe(asyncSave, renderNotes))
# renderNotes는 모든 note가 비동기로 저장된(asyncSave) 후에 한번 호출 됩니다.

_.before

_.before(count, function) 지정 횟수 전까지 함수를 호출 합니다. 그 이후의 호출은 마지막 호출된 값과 같은 결과 값이 나옵니다.

1
2
3
4
5
6
7
greet = _.before(3, lambda when, *r: print('Good', when + '!'))
greet('morning')
# 'Good morning!'
greet('afternoon')
# 'Good afternoon!'
greet('evening')
# 함수가 실행되지 않습니다.

_.negate

_.negate(predicate) predicate 함수 결과(True, False)의 반대를 리턴합니다.

1
2
3
isFalsy = _.negate(_.bool) # _.bool 함수는 인자가 참일때, True, 거짓일때 False를 출력합니다
print(_.find([-2, -1, 0, 1, 2], isFalsy))
# 0

_.throttle

_.throttle(function, wait, [options])은 함수를 받아 새로운 함수 throttled를 리턴합니다. throttled는 처음 호출할때 바로 실행됩니다. 그 이후의 지정된 시간 동안 반복된 호출은 한번만 실행됩니다. 옵션값인 {leading: False}throttled가 처음 실행될 때 기본값과 같이 바로 실행 되는 것이 아니라, 지정한 시간 후에 실행됩니다. {trailing: False}는 지정한 시간 전의 실행은 모두 무효가 됩니다. 즉 throttled가 지정된 시간 전에 반복적으로 호출 되어도 지정된 시간이 지나기 전까지의 호출은 다 무효가 됩니다. 지정된 시간이 지난 후에 호출해야 실행됩니다. 기본 옵션값은 {leading: True, trailing: True}입니다.

1
2
3
4
5
6
7
8
9
10
11
12
def someFunc():
print(datetime.datetime.now())
throttled = _.throttle(someFunc, 0.1)
Timer(0.07, throttled).start()
Timer(0.12, throttled).start()
Timer(0.14, throttled).start()
Timer(0.19, throttled).start()
Timer(0.22, throttled).start()
Timer(0.34, throttled).start()
# 스크롤 할 때, someFunc는 시작할때 한 번 실행된 후 0.1초후에 실행됩니다. 이어서 함수가 실행된다면 0.1초의 간격을 두고 실행됩니다.

_.debounce

_.debounce(function, wait, [immediate]) _.debounce는 함수를 받아 새로운 함수 debounced를 리턴합니다. (1)debounced를 실행하면 지정된 시간이 지난 후 받아둔 함수를 실행합니다. 만일 지정된 시간 전에 debounced가 다시 실행되면 함수 실행은 다시 지정된 시간 이후로 미뤄집니다. [immediate]True를 넘기면 debounced의 첫 번째 실행은 무조건 실행하고, 이 후 실행부터 (1)이 반복됩니다.

1
2
3
4
5
6
7
8
9
debounced = _.debounce(someFunc, 0.1)
Timer(0.07, debounced).start()
Timer(0.12, debounced).start()
Timer(0.14, debounced).start()
Timer(0.19, debounced).start()
Timer(0.22, debounced).start()
Timer(0.34, debounced).start()
# 스크롤이 끝나고 나서 0.1초 후에 someFunc가 실행됩니다. 0.1초가 지나기 전에 다시 함수가 실행된다면, 다시 0.1초가 지나야 someFunc가 호출 됩니다.

Laziness

Partial.py의 L을 이용하면, 파이프라인 내부에서 함수들의 실행 순서를 재배치하여 적절하게 평가를 지연합니다.