Search
Duplicate

Python 프로그래밍 - 기본 문법 함수

Created
6/8/2021, 8:19:00 AM
Tags
Empty
# Python의 변수 호출/참조: Call by Objective Reference대충, call by reference(포인터)랑 비슷한데, 다만 함수안에 전달될 때에는 지역변수 tag가 붙기 때문에 레퍼런스가 사라진다. 또한 List와 같이 mutable한 정보를 담는 자료구조는 indexing을 할 경우 call by reference처럼 행동한다.http://devdoggo.netlify.com/post/python/python_objective_reference/
## Python에서는 + 와 += 가 다르다.a += b 는 inplace이지만, a = a+b 는 새로운 메모리를 할당한다.https://docs.python.org/3.2/library/operator.html#inplace-operators
import sys
print("This is the name of the script: ", sys.argv[0])
print("The arguments are: ", str(sys.argv))
# Python ArgumentParser
args.add_argument('--multi_label', type=int, choices=range(1,5), default=1, help='You can choose the number of tasks(labels). The task should be at least 1.') # 3 # number of labelshttps://docs.python.org/3/library/argparse.html#choiceshttps://stackoverflow.com/questions/25295487/python-argparse-value-range-help-message-appearance
## Argparse에 yes/no 옵션 추가하기
args.add_argument('--download', dest='download', action='store_true') args.add_argument('--no-download', dest='download', action='store_false') args.set_defaults(download=True)
Plain Text
## Argparse에서 여러가지 str input받기
args.add_argument('-no','--no-download', dest='download', action='store_false')
Plain Text
## Argparse에서 2개의 int 받기
parser.add_argument("--exp", type=int, nargs=2, default=None)
Plain Text
## Argparse에서 1개 이상의 string을 받아서 list에 저장하기
parser.add_argument("--run_modes", type=str, nargs="+", default=["train", "valid", "test"])
Plain Text
## 주어진 args or namespace에 대해서 Argparsing하기
parser.parse_known_args(unknown_args)
Plain Text
## Namespace에 dynamic 이름의 변수 할당하기
setattr(conf, dataset_name, dataset_config)
Plain Text
## Argparse 자체 파싱 규칙
augment-data-length 이렇게 된 argument는 parsing되고나면 저절로 augment_data_length 즉 '-'이 '_'으로 바뀌면서 변수명이 정해진다.
# 수동으로 실행 argument 확인하기
물론 argparse를 사용하면 이를 자동으로 파싱해서 입력받는다.
import sys print("This is the name of the script: ", sys.argv[0])print("The arguments are: ", str(sys.argv))
Plain Text

# in 조건 빠르게 탐색하기

if user in user_entry: ~~~
Plain Text
이러한 형태의 조건문을 처리할 때, user_entry가 데이터 타입 list일때는 O(N)이 걸리지만, set일 때에는 O(1)만큼 걸린다.

# Variable 목록

locals() globals() vars()
Plain Text

# Python 변수명 자유롭게 정하기dictionary를 이용하면 변수명을 string으로 지정할 수 있다.
report_dict = {'summary':True, 'scope':locals(),
'train__loss:'+str(m):train_loss[m]}
nsml.report(**report_dict)
# Python 임의의 string으로된 코드를 실행하기
foo = eval("print('asdf')")
이를 응용하여 string으로부터 class obejct를 가져올 수도 있다.
단, 임의의 string이 위험한 코드를 실행 할 수도 있으므로 각별한 주의가 필요하다.https://stackoverflow.com/questions/1176136/convert-string-to-python-class-object
## literal_eval
이러한 eval의 위험성 때문에 많은 제약이 추가된 literal_eval()이 존재한다.
# Python 임의의 string으로부터 class 가져오기archiecture = getattr(sys.modules[__name__], "name of class")
https://stackoverflow.com/questions/1176136/convert-string-to-python-class-object
# Instance로부터 해당 class의 이름 가져오기
a = A()
print(a.__class__.__name__)
# class의 method를 가져와서 실행하기
act_rew_func = ActionReward_function()
action_f = getattr(act_rew_func, meta_conf.exp_conf.action_f)
zero_mask = action_f(None)
# 위의 두가지 하나로 합친 함수
str_to_class(__name__, conf.task_name)(conf)
Plain Text
def str_to_class(module_name, class_name):"""Return a class instance or method from a string reference"""try:module_ = importlib.import_module(module_name)try:class_ = getattr(module_, class_name)return class_except AttributeError:print('Class does not exist')except ImportError:print('Module does not exist')
# DefaultDict
dictionary에 key:value 데이터를 저장할 때, 해당 key가 없는 경우 원래는 if문을 걸어서 dict.keys()에 있는지 없는지 나누어서 처리해야한다. 이런 불편함을 해결하기위해 defaultdict를 사용하면 처음 등장하는 key를 접근해도 keyErrory를 발생시키지 않고 바로 value를 넣을 수 있게 해준다.
아래 두 코드는 동일한 기능을 수행한다.
from collections import defaultdict nor_dict = dict() if k in nor_dict: nor_dict[k].append(1) else: nor_dict[k] = [1]
Plain Text
==>
from collections import defaultdict def_dict = defaultdict(list) def_dict[k].append(1)
Plain Text
## DefaultDict의 초기값 설정하기임의의 값을 return해주는 lambda를 이용한 트릭으로 가능하다. 그 원리는 KeyError상황에서 지정한 callable을 호출하기 때문이라고 한다.
defaultdict(lambda:int(1))
Plain Text
# Dictionary를 obejct의 attribute로 바꾸기
class MyObject(object):
def __init__(self, _dict):
self.__dict__.update(_dict)
# bokeh에서 nodejs 경로를 못잡는문제source activate python362
conda info
conda install -n python362 -c bokeh nodejs
> python 에서 import에러가 뜨면 다음을 실행하여 nodejs의 bin 주소를 PATH에 추가해준다.
import os
os.environ['PATH'] += os.path.abspath(":/home/dhkwak/.conda/envs/python362/bin/")
# 함수 포인터 사용법: 매우 쉬움. 그냥 함수 이름을 변수에 저장하면 끝임.
# Switch문 대체 하는 방법: dictionary이용
def batch_loop(self, run_type="train"): assert run_type in ["train", 'valid', "test"], "You should select run_type among train, valid, test." { 'train': self.set_train_mode, 'valid': self.set_valid_mode, 'test': self.set_test_mode, }[run_type]()
Plain Text
# csv.reader lazy load: csv. reader는 기본적으로 lazy loading이다.https://stackoverflow.com/questions/11109524/can-csv-data-be-made-lazy
# yield 명령어: iterables가 가능한 자료형을 메모리에 전부 올리지 않고, 동적으로 처리하기 위한 generators를 구현하는 문법. 대충 return과 비슷한 역할을 하는데, 차이점은 메모리에서 바로 해제되지 않고 계속 사용가능하다는듯..??
# locals()
locals는 현재 함수에서 사용할 수 있는 모든 지역변수를 dict형태로 return해준다. 따라서 다음과 같은 이용이 가능하다.
a, b, c = 1, 2, 3
def func(a, b, c): print(a, b, c)
func(**locals())
혹은 kwargs를 사용할 경우,
a, b, c = 1, 2, 3
def func(**kwargs):
print(kwargs["a"], kwargs["a"], kwargs["a"])
func(**locals())
그런데 이때 python compiler의 optimization에 의해 locals는 update가 불가능하다. 그렇지만 exec를 한 번 실행해주면, optimization이 실행되지 않으므로, locals()를 업데이트 하는게 가능하다.
그렇지만 이는 거의 해킹에 해당하는 기술이므로, 사용을 권하지 않는다. 그냥 locals()["변수명"]으로 사용하는 것이 가장 정상적인 방법이다.
또는 이러한 방법을 이용해서 namespace에 해당 변수를 할당하는 것을 추천한다.
from types import SimpleNamespace lv = SimpleNamespace(**locals())
# vars()를 이용해서 SimpleNamespace를 dictionary로 변환하기
conf = SimpleNamespace()
conf_dict = vars(conf)
# locals(), globals()
위 두가지 함수를 이용해서 함수를 호출하기 위한 namespace를 가져올 수 있다.
# sorted 기능
sort하고싶은 list를 넣고, key값을 뭘로할지 지정해주면됨. 그런데 이를 쉽게 lambda함수를 이용해서 key를 list에서 뽑아서 지정할 수 있음. 아래 예제 참고
# list를 date string에 따라서 increasing order로 정렬하기
date_code_list = sorted(date_code_list, key=lambda x: datetime.datetime.strptime(x.split("@")[0], '%Y%m%d'), reverse=False)
high_priority_intent = sorted(intents, key=lambda x: intent_to_priority[x], reverse=True)[0]
Plain Text
# N_text형태로 된 string을 숫자의 오름차순 정렬하기
exp_list = sorted(exp_list, key=lambda x: int(x.split("_")[0]))
Plain Text
datetime에서 strptime에 들어가는 format은 다음 레퍼런스를 잠조할 것.대문자 M은 minute를 뜻한다.
import dhkwak_class_and_function as dh # i need prefix dh.
from dhkwak_class_and_function import * # i don't need prefix now
plt.plot -> 점들을 연결해서 그리기
plt.scatter -> 점들을 각각 따로 떨어트려서 찍기
=================
# 점프 투 파이썬을 읽고, 요약 정리한 내용이다.https://wikidocs.net/15
# Python의 특징 : C로 만들어진 python library를 불러와서 사용가능. 즉 Python으로 된 코드가 실제로는 C로 실행이되는것임.
8진수 변수:
a = 0123
16진수 변수:
a = 0x123
제곱 연산자:
3**4 = 81
나눗셈 연산자3/2 = 1.5
나눗셈 후 소수점 내림 연산자:
3//2 = 1
ex) -3//2 = -2
# 파이썬 문자열 다루기
'' 이나 "" 두가지 방법으로 문자열 생성
\' 이나 \" 을 이용하여 문자열내에 특수 기호 삽입
""" 이나 '''을 이용하면 \n을 쓰지 않고, 그냥 엔터를 쳐서 줄바꿈을 입력할 수 있음
문자열 덧셈
'abc'+'defg' = 'abcdefg'
문자열 곱셈
'123'*2 = '123123'
ex) print('='*50)
===================...
문자열 리스트 인덱싱(문자열 객체는 list를 상속받고, 거기에 추가적인 함수를 구현한 듯)
a='abcdefg'
a[2]= 'c'
a[-1]= 'g'
a[0:2] = 'ab'
-> [0,2) 구간임.
0 생략가능
end도 생략가능
ex) a[:] = 'abcdefg'
print format으로 출력하기
print "arg_name: {}, value: {}".format(val1_name, val1)
formatting하기
" %~~ " %( ) 을 이용해서 여러가지 문자열 포멧 출력
5자리 정수 출력하기
print("Number: {:5d}".format(id_card))
# 문자열 formatting --> %2번 사용
정수 삽입: "%d" %3
문자열 삽입: "%s" %'abc'
여러개 삽입: "%d: %s" %(3, 'abc')
그런데 이 때 %s의 경우, 어떠한 자료형이든지 전부 문자열로 변환해서 출력시켜준다. 따라서 형식에 자유로운 장점이 있음.
문자열 formatting을 할 때 %를 출력하려면, %%두번 입력을 한다. \%은 안되나?
문자열 format 정렬과 공백
"%10d" %5
전체 문자열의 길이가 10이고, 오른쪽 정렬
"%-10d" %5
전체 문자열의 길이가 10이고, 왼쪽 정렬
"%5.4f" %0.123
전체 문자열의 길이가 5이고, 소수점은 4자리까지만 출력, 오른쪽 정렬
# 문자열 내장 함수
'abbbc'.count(b) --> 3
'abbbc'.find(c) --> 4. 처음 나온 문자 c의 index를 알려줌. 없으면 -1 리턴
','.join('1234') --> '1,2,3,4'. 우측문자열 사이사이에 ,을 넣어줌
'abc'.upper() --> ABC
'ABC'.lower() --> abc
문자열 치환
'Life is too short'.replace("Life", "Leg") --> 'Leg is too short'
문자열 나누기
"Life is too short".split() --> ['Life', 'is', 'too', 'short']
만약 split함수 안에 ',' 을 넣으면, comma sepration을 하게됨
# 리스트
Python에서는 배열대신 list를 매우 자주 사용한다. C에서의 array와 동일한 기능을 쓰려면 numpy를 쓴다. (python 내장 array는 매우 비효율적임)
## Python List
list() 와 [] 명령어는 다르다.
예를 들어 list(1) 은 int object is not iterable이라는 에러가 뜨지만, [1] 은 그러한 에러가 뜨지 않는다.
[https://stackoverflow.com/questions/19523563/python-typeerror-int-object-is-not-iterable](https://stackoverflow.com/questions/19523563/python-typeerror-int-object-is-not-iterable)
또한 list([1]) 을하면, 그냥 다시 [1]이 되지만 [[1]] 을 하면 list안에 또 list가 들어있다.
a = [ ] (a = list()도 가능)
b = [1, 2, 3]
c = ['Life', 'is', 'too', 'short']
d = [1, 2, 'Life', 'is']
e = [1, 2, ['Life', 'is']] --> 리스트 안에 리스트를 넣음
list 수정
a = [1,2,3]
a[1:2] = 'abc'
-> [1, 'abc', 2]
list 엘리먼트 삭제
del a[0] --> 0번 엘리먼트 삭제
list 내장함수
문자열 리스트와 대부분의 기능 공유함.
리스트 덧셈, 반복, count() 등
a.append(5) --> 뒤에 5를 덧붙임
a.pop() --> 맨 앞의 원소를 꺼내옴(삭제하면서)
a.pop(index) --> 해당 인덱스를 꺼내옴
a.extend([리스트]) --> list + list 연산
a.sort() --> 오름차순 정렬
a.reverse() --> 역순
a.insert(index, element) --> 가운데에 끼워넣을수있음
a.index(값) --> 처음나온 해당 값의 인덱스 리턴
a.remove(값) --> 처음나온 해당 값의 엘리먼트를 삭제
특별한 조건 연산자
if 1 in [1, 2, 3] --> True
if 1 not in [1, 2, 3] --> False
Python에서 어떤 조건문에 아무것도 실해하고 싶지 않을 때, pass를 사용한다
if 'money' in pocket:
pass
in문법을 if와 사용하면, 엘리먼트 체크의 기능이 되고, for 문과 연동하면 list에서 엘리먼트를 하나씩 가져오도록 사용할 수도 있음.
a = [(1,2), (3,4), (5,6)]
for (first, last) in a:
print(first + last)

Class와 Instance의 차이

어떤 class를 정의한 다음, 해당 클래스를 initialize하면 instance가 생성된다.

# Method의 종류

class MyClass: # This part is Class definition. # It has same effect with classmethod, but it is always executed when the class module is loaded. # So it is hard to control the flow. Therefore if you need a kind of shared computation, use classmethod. def method(self): # instance method return 'instance method called', self @classmethod def classmethod(cls): return 'class method called', cls @staticmethod def staticmethod(): return 'static method called'
Class method: 오직 class 변수만 접근한다. class 변수를 바꾸어, 모든 instance에 영향을 줄 수 있다.
Static method: class 혹은 instance의 아무런 변수도 필요로하지 않는다.
Instance method: 오직 instance 변수만 접근한다.
Class definition part: 이곳에 선언된 코드는 class method와 기능적으로는 완전히 동일하지만, class를 선언하는 시점에서 반드시 1회 호출이 되고 cls를 생략하고서 변수를 정의할 수 있다. Class module을 로딩하기만해도 즉시 호출되기 때문에 호출여부나 시점을 control 할 수 없으므로, class간에 서로 공유하는 정보나 연산이 필요한 경우 class method를 따로 정의해서 사용하는 것이 바람직하다.

# Method 선언시

Always use self for the first argument to instance methods.
Always use cls for the first argument to class methods.

# Variable의 종류

Class variable: ClassName.name으로 접근하거나, class_method안에서 cls.name으로 접근한다.
Instance variable: instance_name.name으로 접근하거나, instance_method안에서 self.name 으로 접근한다.

# Special Variable

python에는 built-in 으로 제공되는 특수한 변수가 있다.
__name__ : 현재 코드가 위치한 패키지의 경로와 이름이 저장되어 있다. 단, main의 경우만 __main__으로 나타나고, 다른 패키지는 import 경로와 동일하다.
ex) if __name__ == "__main__":
main함수 실행시 동작 코드 작성
__file__ : 현재 코드의 절대 경로가 저장되어 있다.
ex) os.path.dirname(__file__)     으로 현재 파일의 상위 dir을 가져올 수 있다.
# Project 내부에 속한 파일을 읽어들일 때
PROJECT_ROOT = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
Plain Text
프로젝트가 module로 사용될 때에는 기본 경로가 실행파일의 위치이기 때문에 프로젝트 root에 상대적인 경로로 파일을 읽어들여야만 경로 참조 시 문제가 생기지 않는다.

Stdout을 파일로 저장: Logging

stdout을 file stream에 연결하는 방법

import sys sys.stdout = open('file', 'wt') print('test') sys.stdout.close()
위와 같은 방법으로 해버리면 아주 간단히 print로 출력된 모든 string을 해당 파일로 저장시킬 수 있다.
그러나 이렇게 하면 print로 출력되는 것은 더이상 볼수 없게 된다. 또한 stdout을 이렇게 쓰면 여러가지 불안한 문제점또한 존재한다.

logging 사용하기

logging모듈을 사용하면 stdout으로 출력할 수도 있고, 파일로 출력할 수도 있고, 또 동시에 출력할 수도 있다.
맨 앞에서 한 번 config해 놓으면 print랑 같은 방식으로 사용할 수 있고 third 파티 앱과 통합된 방식으로 쉽게 로그 관리가 가능하다. 그리고 log가 호출된 모듈(함수)위치를 알아낼 수 있음. 로깅레벨에 따라서 필터링할 수 있는 것도 장점임.(한번에 print를 안보이게 할 수 있음)
다음의 config를 사용하면, stdout과 파일로 동시에 출력 가능.
import logging
reload(logging)
logger = logging.getLogger('program_name')
logger.setLevel(logging.INFO)
fh = logging.FileHandler('logfilename.log')
fh.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s %(name)s [%(levelname)s] %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)

range, xrange, arange

http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range
range(start, stop, step) : default built-in function to make the sequential list of integer
xrange(start, stop, step) : default built-in function to get the sequential index of integer. not really make the list so it's much faster but can't get the real index value
arange(start, stop, step) : numpy api to use the range in matrix domain
# Argument Passing with List or Dictionary
파이썬에서는 함수에 인자를 전달할 때, list나 dictionary를 이용해서 한 번에 인자를 전달할 수 있다.
def function_A(a , b, c):
return a+b+c
이러한 함수가 있을 때 다음의 세가지 방식으로 호출할 수 있으며, 서로 완전히 같은 기능을 한다.
1) Normal
function_A(a=1, b=2, c=3)
2) List
arg = [1, 2, 3]
function_A(*arg)
3) Dictionary (단, 반드시 함수의 argument이름과 dictionary의 key이름이 같아야한다.)
arg = {"a": 0, "b": 1, "c": 2}
function_A(**arg)
# 이때, **은 dictionary의 포인터를 전달하는 것이고, *은 list의 포인터를 전달하는 것이다.

List와 Set을 함께 쓸 때 주의할 점

set은 element들의 순서를 고려하지 않는 집합이므로, list(set(~~))을 수행하고나면, 그 결과물의 순서가 랜덤하게 바뀐다. 이 순서는 해당 element의 메모리 주소로 결정되기 때문에 심지어 random.seed를 fix하더라도 계속해서 바뀐다. 따라서 이러한 문제가 없도록 하려면 sorted()를 사용하거나, 혹은 orderedDict같은 자료구조를 사용해야한다.
list에 들어있는 element들의 개수를 세서 dictionary 형태로 바꿔주는 함수이다. 또한 반대로, counter로부터 해당 element들을 가진 list를 생성시키는 것도 가능하고, counter끼리 덧셈/뺄셈도 가능하다.
from collections import Counter c = Counter('gallahad') print(c) >> Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1})
Python
from collections import Counter c = Counter(a=4, b=2, c=0, d=-2) sorted(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
Python

# args, **kwargs를 이용해서 함수 인자 정의하기

python에서 함수를 정의할 때, 입력받을 argument들을 명시적으로 fix시키지 않고 정의할 수 있는 방법이 있다.
args는 함수에 인자를 list형태로 전달받는 경우로, non-keyworded argument만 처리할 수 있다.
ex) def test_args_fun(*args):
~~~
test_args_fun(1, 2, 3, key, value)
*kwargs는 함수에 인자를 dictionary형태로 전달받는 경우로, keyworded argument만 처리할 수 있다.
ex) def test_kwargs_fun(**kwargs):
~~~
test_args_fun(one=1, two=2, three=3, key=key, value=value)

# 투명한 함수 정의하기

입력 받은 변수 그대로를 다른 함수에 전달해주는 구현
def forward(self, *args, **kwargs): return self.layer(*args, **kwargs)
# 전역 변수 사용
전역 변수로 선언한 변수를 함수 내부에서 호출 시 기본적으로 인식을 하지 못한다.
이런 경우 함수 내부에 "global 변수명" 를 한 번이라도 선언하고 실행해주면, 그 뒤로는 모든 함수에서 global 변수 사용이 가능하다.
아래 링크 참조.
# Python Class
클래스 instacne를 저장하고 불러오기
핵심은 pickle을 이용해서, self.__dict__ 를 저장하고 불러온 다음, self.__dict__.update(loadings) 를 해서 객체를 업데이트 시켜버리는 것임
ex) 클래스가 자기 자신의 instance를 저장하고, 불러오는 예제    def save(self):        with open('MountainCar_demonstration.pkl' , 'wb') as f:            pickle.dump(self.__dict__, f , pickle.HIGHEST_PROTOCOL)        def load(self):        path = os.path.join('..', 'IRL_tensorflow', 'MountainCar_demonstration.pkl')        with open(path, 'rb') as f:            tmp_dict  = pickle.load(f)        self.__dict__.update(tmp_dict)
클래스 상속
class extention -> class MyClass(parent class):
마찬가지로 함수 overriding도 가능.
클래스 조건부상속(Conditional Inheritance)
상속을 받는 () 안에 if, else문을 이용해서 조건부 상속이 가능하다. (반드시 함수를 정의해서 할 필요는 없음)
def MountainCarFunction(conf):
class MountainCarEnvironment(ModelEnvironment if conf.model_based is True else Environment):
return MountainCarEnvironment(conf)
내부클래스 / 내부함수
어떤 클래스의 내부에서만 선언될 클래스는 다음과 같이 inner class로 선언할 수 있다. 아래 코드는 연속된 계층구조를 맞춰서 다음과 같은 접근이 가능하다.
class ModelInteraction(object):
class observation_space(object):
def __init__(self):
self._shape = 0
@property
def shape(self):
return self._shape
@shape.setter
def shape(self, value):
self._shape = value
class action_space(object):
def __init__(self):
self._n = 0
@property
def n(self):
return self._n
@n.setter
def n(self, value):
self._n = value
def sample(self):
return random.randrange(1, self._n)
def __init__(self):
self.action_space = action_space()
self.observation_space = observation_space()
-> 다음과 같은 접근이 가능하다!
self.interaction.observation_space.shape = 2 #action size in the model being learned
self.interaction.action_space.n = 3 # observation size in the model being learned
@property
@V.setter
http://egloos.zum.com/nemonein/v/5280842
http://bigbigdata.tistory.com/69
특수 메서드
__init__ 이외에 __repr__와 같은 매우 유용한 특수 메서드가 클래스에 존재한다.
클래스 상속시 __init__함수의 작동방식
1) 상속받은 클래스를 생성하면 일단 기본으로 부모의 __init__이 호출된다.2) 그런데 상속받은 클래스에 __init__함수를 따로 overriding하면, 부모의 __init__은 더이상 호출되지 않는다.3) 만약 부모의 __init__도 호출하고 싶으면, 상속받은 클래스에서 overriding한 __init__에서 다음의 코드를 한줄 추가해서 명시적으로 부모의 __init__을 호출시켜주어야 한다..def __init__(self):    super(자식클래스이름, self).__init__()# super(자식클래스, self)를 하면 자동으로 부모클래스가 지정된다. 아니면 직접 부모클래스.__init__() 이렇게 해도 동일함.
------
[output] + return_states = list(output).extend(return_states_
# 파이썬 딕셔너리:- 중복이 불가능한 해시테이블. 순서정보가 없이 쌍으로 이루어진 데이터를 저장하는 데 용이. 선언은 {}으로하고, 이후사용은 리스트처럼 []으로함. 마찬가지로 del이나 in사용가능. 키스, 벨류스, 아이템스 함수와 클리어 함수가 있음. 키값으로 변하지않는 데이터를넣어야하므로 리스트는 쓸수없지만, 튜플은 가능. 벨류로는 무엣이든지 가능.
HDF5 읽어서, key값을 인덱싱할 때 ['trainingX'] 이렇게 문자열로 인덱싱하는걸 딕셔너리라고 함.
딕셔너리에서 [1]을 하면, 이건 1번째 데이터에대한 인덱싱이아니라, key값이 1로 지정된것일 뿐임.
데이터를 추가하고 싶으면 dict['새로운 key'] = value 를 치면 됨. 삭제는 del dict['삭제할 key']
주의할 점은, key가 중복되게 넣어버리면, 어떤게 살아남을 지 모른다는것.(덮어씌여지는 순서가 랜덤임)
그리고 딕셔너리에서 여러개를 동시에 읽고싶으면, key들을 list가 아니라 tuple로 만들어서 넣어야함. (list는 값이 바뀔수 있어서안된다고함)
아하. hdf5.keys()에서 이 keys()가 딕셔너리 함수였구나
https://wikidocs.net/16
튜플이란 리스트와 몇 가지 점을 제외하곤 모든 것이 동일하다. 그 다른 점은 다음과 같다. 핵심은 값을 수정하지 못하는 것.
리스트는 [ 과 ] 으로 둘러싸지만 튜플은 (과 )으로 둘러싼다.
리스트는 그 값을 생성, 삭제, 수정이 가능하지만 튜플은 그 값을 변화시킬 수 없다.
파이썬은 ||이없다. 대신 or를 써야한다.
파이썬에서 메모리 강제 삭제
del ~~~ 하면 바로 메모리에서 날아감.
아이파이썬 단축키
# Tap : automatic completion
# ctrl + / : comment
아이파이썬 다큐멘테이션
? vgg_model.compile
esc b : below에 cell 셍성
esc a : above에 cell 셍성
아이파이썬 interact 바 두개 쓰기
interact(plot, z1=(0, 1, 0.1), z2=(0, 1, 0.1))
float is not callable
이 에러는 변수명하고 함수명이 똑같을때 발생한다.
-----
for 문에서 count 쉽게하기 : enumerate를 사용한다.
for i, layer in enumerate(self.layers):
x = layer(x)
if type(layer) is Flatten:
x = tf.concat(1, [x , input_list[1]])
파이썬은 {} 대신 tab을 영역으로 사용함.
변수의 타입을 지정하지 않음. 자바스크립트처럼 알아서 변수 타입을 지정함.
파이썬은 기본적으로 모든 변수가 지역변수임. 그런데 global 을사용해서 여기서 선언한 지역변수를
다른데서도 참조할 수 있는 기능이있음
파이썬은 걍 실행시킨 파일의 위에서부터 쭉 실행됨.
그래서 함수정의가 위에서 선언되어야 아래에서 사용가능.
근데 전역변수 선언은 아래에 해도되는듯.
cnt ++은 안됨. cnt += 1 은 됨
=====
for cnt in range(0,10):
print(cnt)
====== 주석달기
한글 주석은 쓰지말라는듯 /  # -*- coding: utf-8 -*-  / 쓰러면이걸 파일 맨위에 선언하고하라는듯함.
# : 한줄짜리
" ~ " : 한줄짜리
""" ~ """ : 여러줄짜리
======= 함수 정의
def 함수명(인자, 인자) :
내용
return 반환변수
----- 리스트
리스트는 기본적으로 배열임.
근데 배열에 좀더 기능이 이것저것 추가된것임.
리스트의 리스트는 걍 2차원 배열임
리스트에서 특정 아이템을 삭제하려면?
for cnt in range(0,kinect_nframes):
del kinect_frames[cnt][1
예외처리
try :    ~~~except:       /        except 특정에러 as e :   (e는 에러 메시지를 의미)
~~~
print 이어 붙여서 출력하기
print "arg_name: ", val1_name, "value: ", val1
3가지 주요 자료형 선언 방법
instance_list = []
instance_tuple = ()
instance_dictionary = {}
# Dictionary 합치기(겹치는 key에 있어서는 new_dict가 old_dict를 덮어쓴다.)merged_dict = dict(old_dict, **new_dict)
tuple에서의 extend
(0 , )+ tuple(1,2,3) => (0, 1, 2, 3)
List 를 tuple로 바꾸기
tuple([ 1, 2, 3 ]) 하면
[1, 2, 3] -> (1, 2, 3) 으로 바뀜
List 의 expend 와 append의 차이
append는 list안에 list를 추가하는 것이고
extend는 list의 원소를 가져와서 기존 list에 추가하는 것임.
즉 extend의 결과는 항상 1개의 list이지만
append를 하면 list안에 list가 존재하게 된다.
---- 제곱
7 ** 3 하면 7의 3이 나옴
걍 함수밖에서 , 0번째 탭에 실행시키면 자동실행됨
파이썬에서의 매틀랩 unique에 해당하는 함수는 set(X)임
eda,kinect,cert=0,0,0
변수는 이런식으로 선언하고 초기화. 아니면
window_size, step_size,  time_lag, EDA_m1,  EDA_m2,  EDA_m3,  EDA_m4,   EDA_median=[0]*8
eda,kinect,cert=0 이렇게 하면, 런타임 에러뜸
if(조건) :
#꼭 : 을 써줘야하네
다른 py파일에 있는 함수 쓰려면 그냥 import 한다음 XXXX.~ 찍어서 쓰면됨
형변환은 (type)~~ 하면됨
str에서 split 함수 쓰면 배열에다가 문자열을 쪼개서 집어넣어줌.
ex) str(ConfigFile.getStepsize()).split('.')[0] / 하면 점 앞에숫자만 쓴다는것임
http://hy3na.tistory.com/91
파이썬에서 static을 쓰려면 클래스를 선언해야함.
는  안되네 걍 global 선언
global도 희안하게, 선언은 걍해주고, 실제가져다 쓸때 global을 붙여서 쓰네
static = global로 해결은 잘안됨
static 은 클래스로 해결해야함.
-----
global 은 걍 c에서 전역변수 선언해놓은거를 함수안에서
"사용할때는" global을 먼저 선언하고 사용해라라는 규칙임.
그래서 밖에다가 일단 전역변수 선언 후, 함수맨위에서 사용할
전역 변수들에 global을 한번씩 써주고 사용하면됨.
결론 -> 전역변수를 함수안에서 사용할때 global로 한번 명시해놓고 써라!
무조건 global해야됨. 안그러면 지역변수로 새로 생성해서 써버리네
class Myclass:
x=10
myInstance = Myclass() //로 인스턴스 생성
myInstance = Myclass //하면 인스턴스가아니라 클래스 obj가 나온다고함.
메서드 선언할때는 self가필요하네..
http://openlook.org/blog/2008/12/13/why-self-in-python-is-attractive/
https://wikidocs.net/28
클래스라는 것은 뽑기의 틀(별모양, 하트모양)과 비슷하다.
별모양의 틀(클래스)로 찍으면 별모양의 뽑기(인스턴스)가 생성되고
하트모양의 틀(클래스)로 찍으면 하트모양의 뽑기(인스턴스)가 나오는 것이다.
즉, 클래스란 똑같은 무엇인가를 계속해서 만들어 낼 수 있는 틀
인스턴스란 클래스에 의해서 만들어진 뽑기를 뜻하는 것이다.
클래스 선언 ex)
class configfile:
window_size=0
step_size=0
time_lag=0
EDA_m1=0
def __init__(self, window_size):
self.window_size = window_size
def Read_config_file(self):
self.index_start,index_end = 0,0
self.config_buffer=[0]*100
self.count_line = 0
## self 란,
self란 자기자신의 instance를 가리키는것.
기본적으로 메서드 첫번째에 선언되어야함.
그리고 class내부의 변수를 사용할때는 꼭 self.으로 사용해야함
- 생성자
def __init__(self, window_size):
self.window_size = window_size
요런식으로 c 생성자처럼 사용함.
def __del__(self, )는 소멸자
--
클래스를 걍
fr = ReadData.FileReader() 이렇게 생성만해도,
알아서 클래스의 맨위에서부터 쭉 실행이됨 ㅋㅋ.
클래스를 걍선언해놓는건 만으로도 쫙 위에서부터 실행하네
아니 그냥 모든 파일의 위에서부터 다실행 하는 듯.. 매우 C스럽다
걍 클래스가 한번 임포트 되기만해도, 위에서부터 실행시켜버림
그래서 제어를 하려면, 무조건 생성자 안에다가 넣어야되나?
근데 그러면 또 클래스의 변수를 접근할 수가 없네
Python list comprehension : i 번째 원소를 list에서 반복적으로 연산하여 저장할 수 있음.
list에서의 Permutation Indexing 을 위의 기능을 이용해서 구현할 수 있다.
예제 1)
np.random.seed(1234)
permuted_index = np.random.permutation(len(full_path))
labels = labels[permuted_index] # numpy는 걍 이렇게 하면됨. 매틀랩 처럼.
from random import shuffle
shuffled_full_path = [full_path[i] for i in permuted_index] # list에서는 list comprehension을 써야함.
예제 2)
threshold = 0.000001
reward_feature = [threshold if val < threshold else val for index, val in enumerate(reward_feature)]
예제 3)
>>> l = [22, 13, 45, 50, 98, 69, 43, 44, 1] >>> [x+1 if x >= 45 else x+5 for x in l] [27, 18, 46, 51, 99, 70, 48, 49, 6]
Plain Text
## Dictionary comprehension- list comprehension하고 거의 비슷한 방법으로 사용가능
report_dict = { key:item.astype(np.float64) if item.dtype=='int64' else item for item, key in zip(report_dict.values(), report_dict.keys())}
## List comprehension의 응용
1) 단순히 list를 생성하는 목적이 아니라, for loop의 one line command로써도 아주 잘 사용 가능하다. 특히 tuple( print(a), print(b) )로 여러개의 명령어를 묶으면 한줄에 여러개 실행이 가능하다.
2) 또는 if 문에 다음과 같은 trick을 써서 time delay를 줄 수도 있다.[print(a) for s in sessions if time.sleep(1)==None]
List repeat
bounds = [0, 256] * 100
Bound check
if action in range(self.action_size+1) is True:  # 이때 반드시 range +1을 해주어야 제대로 체크됨. 정수만됨
return action
else:
raise error
이상하게 버그가 있는듯.. 그냥 if 문 사용하는게 안전해보임.
-
array[-1]
과 같이 음수 인덱스는 반대방향 인덱스를 의미한다. 즉 [-1]은 맨 마지막 인덱스이고, [-2]는 맨마지막에서 왼쪽 인덱스이다.
-
Numpy 에서 4d zeros만들기
4d_zeros = numpy.zeros((1,2,3,4))
괄호를 두번 쳐줘야한단다.
-
matplotlib로 opencv로 그린 이미지를 IPython에 출력하기
%matplotlib inline
Plain Text
import cv2 import numpy as np import matplotlib.pyplot as plt
Plain Text
img = cv2.imread('/Users/ayang/Pictures/ForTest/test.jpg') img = cv2.cvtColor(img, cv2.cv.CV_BGR2RGB)
Plain Text
Plain Text
#plt.imshow(img) # the order of RGB is not same with opencv
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
Plain Text
#matplotlib 에서 quiver 사용시에는 매우 조심해야한다.
pylab.quiver(x, y, u, v, angles='xy', scale_units='xy', scale=10)
Plain Text
다음 format이 무조건 default 호출이어야한다.
------------------------
Python
Lambda function : 람다함수는 일종의 인라인 인스턴트 함수이다.즉 어떠한 기능을 수행할 때 함수를 코드상에서 바로 구현해서 실행시켜버리는 인스턴트 함수 정의임.
String operator : + 는 공백 없이 string을 붙이고 , 는 공백을 포함해서 붙인다.
print('one', 'two')
>> one two
print('one' + 'two')
>> onetwo
Super Overhead
파이썬에서 list 에다가 for loop을 돌면서 매 iteration마다 append를 하고, 이걸로 np.mean 같은걸 계산하면 정말 속도저하가 엄청나게 심각하다. 이런식으로 코딩을 하면 np.mean 계산 속도가 list의 길이와 비례해서 선형적으로 무한히 증가한다.
collection
여러개의 데이터 타입을 하나의 객체로 묶어서 사용할 수 있게 한다. dictionary와 매우비슷한데 보다 추상적임
numpy.random.permutation : 순서를 뒤섞은 객체를 return함
numpy.random.shuffle : input으로 넣은 대상의 순서를 뒤섞어줌(return이 없다)
from ~~~ import ~~~ 구문을 if문 아래에서 가져올 수 있음.
flag사용법
flag에서 conf를 어떻게 정의한거지?
-> 아, flags.DEFIN으로 정의한 모든것을 가져오는구나
tmp_list = []
tmp_tuple = ()
tmp_dictionary = {}
assert : Should be True 여야하는 조건을 체크한다.
크리티컬한 문제가 생길 수 있는 부분에 적극 활용할 것,
제시한 조건은 언제나 항상 성립해야함. 만약 필수 조건이 성립하지 않으면, 우측의 에러 메시지를 발생시킴.그런데 다음과 같이 괄호를 잘못 사용하면 안됨. 괄호를 사용해버리면 파이썬 문법적으로 항상 False가 나와서 에러가 뜨지 않음.......... 그냥
assert(2 + 2 == 4, "Houston we've got a big problem")
Plain Text
그래서 assert를 쓸 때는 다음과 같이 항상 괄호 없이 사용할 것!!!
assert 2 + 2 == 4, "Houston we've got a big problem"
Plain Text
assert의 의미 : assert if the condition is false
즉 해당 조건이 만족되지 않으면, 에러를 발생 시킴
다음 둘은 서로 동일함.
assert condition
if not condition:
raise AssertionError()
## 삼항연산자: python에서는 if else 구문을 이용해 다음과 같은 삼항연산이 가능하다.comparison = (True) if a == b else (False)
## 변수 연속할당A = B = C
이런식으로 변수 대입/할당이 가능
reversed(range(self.history_length)) : 역순으로 세기
python tuple to list/list to tuple
list(tuple instacne)
tuple(list instacne)
Python Class
클래스 instacne를 저장하고 불러오기
http://stackoverflow.com/questions/2709800/how-to-pickle-yourself
핵심은 pickle을 이용해서, self.__dict__ 를 저장하고 불러온 다음, self.__dict__.update(loadings) 를 해서 객체를 업데이트 시켜버리는 것임
ex) 클래스가 자기 자신의 instance를 저장하고, 불러오는 예제    def save(self):        with open('MountainCar_demonstration.pkl' , 'wb') as f:            pickle.dump(self.__dict__, f , pickle.HIGHEST_PROTOCOL)        def load(self):        path = os.path.join('..', 'IRL_tensorflow', 'MountainCar_demonstration.pkl')        with open(path, 'rb') as f:            tmp_dict  = pickle.load(f)        self.__dict__.update(tmp_dict)
클래스 상속
class extention -> class MyClass(parent class):
마찬가지로 함수 overriding도 가능.
그리고 클래스 상속을 한다음, 만약 부모 클래스가 __init__에서 무언가 기능을 하고 있다면, 반드시 자식 클래스의 __init__에서 super의 __init__을 호출해주어야만 함. 안그러면 아무런 동작도 하지 않는 게 됨. 파이썬은 보여지는 코드가 전부 다임. 그 이상 숨겨진 동작은 하지 않음.
클래스 조건부 상속
1. class newClass(A if os.name == 'nt' else B):2. RLAgent = DistributedAgent if m_conf.e_conf.distributed else CentralizedAgent
3. class RLAgent(eval(Config.AGENT_TYPE)):
Config.AGENT_TYPE = "DistributedAgent" if e_conf.distributed else "CentralizedAgent"
import RLAgent # 반드시 import 를 나중에 해주어야함.
사용해보니, 3번 방식이 가장 편리함.
클래스의 조건부 리턴(조건부 상속 목적으로 사용하면 안됨)
https://spyhce.com/blog/understanding-new-and-init클래스가 어떤 객체를 반환할지는 __init__에서 결정할 수가 없다. 그래서 __new__ 함수를 이용해서 어떤 클래스를 실제로 사용할 결정할 수가 있다.(상속이 아니다. 그냥 다른 class를 가져와서 반환하는 것이다.)(단, 이 경우 object를 먼저 상속 받아야함)
__new__ 함수는, 어떤 방식으로 __init__을 할지를 결정하는 method이다. 객체를 생성하게 되면 언제나 __new__가 제일 먼저 호출되고 ,보통 그 다음에 __init__이 호출된다. 따라서 이 __new__함수를 통해서 __init__에 대한 동작 규칙을 정의할 수 있다. 이를 통해서 signleton 패턴 또한 쉽게 구현가능하다. 간단히 설명하면 객체 생성이 요청되었을 때, __new__를 정상적으로 호출해서 __init__을 호출 시킬지, 아니면 그냥 이를 무시하고 기존에 생성해둔 객체를 리턴할지 정하는 것이다.
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
또한 아래와 같이 상황에 맞는 class를 type을 생성시키는 것도 가능하다.
즉 __new__는 어떤 방식으로 객체를 생성(__init__ 등)할지를 정의하는 함수이다.
class Test(object)        def __new__(cls, conf, observation_dims):            if conf.model_based is True:                return Model_Environment(conf, observation_dims)            else:                return Environment(conf, observation_dims)
클래스의 조건부 상속
조건부 상속을 하려면 아래의 링크처럼, 상속을 받는 calss A()이 괄호안에 if, else 문을 사용해야한다.
클래스의 메서드를 외부에서 정의한 함수로 Overriding하기
먼저 다음과 같이 오버라이딩 하고 싶은 함수를 전역함수로 정의한다.
def custom_function(   해당class  , argument1, argument2 ...    ):
return ~~~
그리고 나서 해당 클래스의 메서드에 function pointer를 대입한다.
ClassA.original_function = custom_function
이때 중요한 점은 임의로 정의한 함수의 첫 번 째 인자는 클래스 메서드의 self를 대체하는 변수라는 것이다. 그래서 마치 self 처럼 사용할 수가 있다.
클래스에 static 변수 선언하기
self를 안붙이고, class내부에 선언하면 된다고 함.
# 파이썬은 금지된 규칙이 거의 없다.
심지어 부모 클래스에서 자식 클래스의 method를 호출할 수가 있네.....; 단, 호출시 자식클래스로 생성한 객체에서만 호출 가능. 즉 부모 클래스는 오직 추상 클래스로만 사용되고 있어야함.
http://stackoverflow.com/questions/25062114/calling-child-class-method-from-parent-class-file-in-python
TOP