본문 바로가기

Python/Basic

Python - 기본 문법정리

* 목차

1. 주석

2. 변수

3. 연산자

4. 변수 선언

5. 조건문

6. 반복문

7. 함수

8. 클래스

 

 


주석(Comments)

python에서 지원하는 주석인 #과, 주석처럼 사용하는 Triple quotes가 있습니다. Triple quotes는 실제로는 string 객체지만, 주석으로 사용을 많이 합니다.

 

Comment : #을 사용하며, 글자 뒤에 한 줄만 적용 됩니다. print해도 출력할 수 없습니다.

# 주석1 입니다.
# 주석2 입니다.

 

 

Triple quotes : 큰 따옴표, 작은 따옴표를 사용하여 여러 줄에 적용합니다. print로 출력할 수 있습니다.

"""
document explain1
document explain2
"""

'''
document explain1
document explain2
'''

 

 


변수(Variable)

python에서 지원하는 다양한 Type이 있습니다.

 

None Type : 아무것도 아님을 나타내는 Type입니다.

None		# NoneType : NULL, null, 없음을 뜻하는 객체

 

 

Boolean Types : 참, 거짓을 나타내는 논리적 Type입니다.

True      	# True == 1이다.
False      	# False == 0이다. 참고로 None은 True, False와 모두 일치하지 않는다.

 

Numeric Types : 숫자를 표현하는 Type입니다. int, float, complex가 있습니다.

# int
10
int(4.2)   	# 4
int('42')  	# 42

# float
3.14           	
float(3)       	# 3.0
float('3.14')  	# 3.14

# complex
(3.25 + 20j)          	# 허수를 j로 표현합니다.
complex(3.14, 9.9)  	# 3.14+9.9i

 

Sequence Types : 시퀀스 Type입니다. 각 요소를 index를 통해 접근할 수 있습니다.

# list : 나열 개체
[1, 1, 2]     	
list([1, 2, 3])

# tuple : 수정이 허용되지 않는 나열 개체
(1, 2, 3)      	
tuple([1, 2, 3])

# range(start=0, stop, step=1)	# range : 시작, 끝, 단계를 가지고 있는 나열
range(5)       	# [0, 1, 2, 3, 4]를 출력할 수 있다.
range(0, 5)    	# [0, 1, 2, 3, 4]를 출력할 수 있다.
range(0, 5, 1) 	# [0, 1, 2, 3, 4]를 출력할 수 있다.

 

Text Sequence Types : 문자열(String) Type입니다. Single quote와 Double quotes, Triple quotes 형식이 있습니다.

# Single quotes. 안에 큰 따옴표가 필요할 때 사용한다.
'ab"cd"efgh'

# Double quotes. 안에 작은 따옴표가 필요할 때 사용한다.
"ab'cd'efgh"

# triple quotes. new line도 표현하고자 할 때 사용한다.
"""
ab'cd'
efgh
"""        	

'''
ab"cd"
efgh
'''

 

Binary Sequence Types : 이진 시퀀스 Type입니다. Bytes, Bytearray, Memoryview가 있습니다.

>>> a = b'abc'       	# bytes 선언. 변경할 수 없는 ascii 데이터이다.
>>> bytes(3)        	# int값을 넣으면 비어있는 byte를 3칸 생성한다.
b'\x00\x00\x00'
>>> bytes([1, 2, 3])   	#  list 형태로 선언할 시, 0 ~ 255 int값만 허용한다.
b'\x01\x02\x03'
>>> bytes(list(range(256)))		# 한번 해보시길 추천.
>>> a = bytes(
b"""
abcd
efgh
""")                          	# bytes도 string과 마찬가지로 '', "", """문법을 지원한다.
>>> "hello".encode()         	# string에서 encoding하면 bytes로 전환한다.
b'hello'
>>> b'\x61\x62\x63'.decode()	# bytes를 decoding하면 string으로 전환한다.
'abc'
>>> repr(b'\x61\x62\x63')      	# 바이트 표현을 문자열 표현으로 전환한다.
b'abc'


>>> a = bytearray(b'hello')    	# bytsarray선언. 변경 가능한 byte data이다.
>>> a[0] += 1                 	# bytes type에서는 불가능한 동작이다.
>>> print(a)
bytearray(b'iello')


>>> byte_data = bytearray(b'hello') # memoryview는 byte-like(+array) data만 viewing할 수 있다.
>>> mem_v = memoryview(byte_data)  	# memoryview는 python에서 pointer같이 동작한다.
>>> mem_v
<memory at 0x000001C1067C8A00>   	# memoryview는 주소 그 자체이다.
>>> mem_v
>>> mem_v.obj                     	# memoryview가 가리키고 있는 값
bytearray(b'hello')
>>> hex(id(mem_v.obj))             	# memoryview가 가리키는 주소
'0x1c1068221b0'
>>> hex(id(byte_data))            	# 그 주소가 byte_data 주소와 동일한지 확인

 

Set Types : 순서가 없고 중복이 불가능한 Type입니다. 순서가 있는 sequence보다 성능면에서 유리합니다.

# set : 수정이 가능한 set 객체
{1, 2, 3}
set([1, 2, 3])

# frozen set : 수정이 불가능한 set 객체
frozenset([1, 2, 3])

순서가 없기 때문에, index 사용이 불가합니다.

>>> a = {1, 2, 3}
>>> a[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object is not subscriptable

 

Dict Types : 순서가 없고 중복이 불가능한 key-value 기반의 Type입니다.

{'a': 1, 'b': 2}
dict([('a', 1), ('b', 2)])

 

 


연산자(Operator)

연산자는 여러가지 기호들로 되어 있으며, 각 기호는 함수와 대응됩니다.

주석에는 예상 결과값과 연산자에 대응되는 함수를 표기했습니다.

 

산술(Arithmetic) 연산자. 

+11        	# 11   pos(a)
-11        	# -11  neg(a)
11 + 2  	# 13   add(a, b)
11 - 2	  	# 9    sub(a, b)
11 * 2   	# 22   mul(a, b)
11 / 2  	# 5.5  truediv(a, b)
11 // 2   	# 5    floordiv(a, b)
11 % 2    	# 1    mod(a, b)
11 ** 2 	# 121  pow(a, b)

 

비교(Comparison) 연산자

1 == 1    	# True 	  eq(a, b)
1 != 2    	# True    ne(a, b)
1 < 2    	# True    lt(a, b)  less than
2 > 1    	# True    gt(a, b)  greater than
0 <= 0    	# True    le(a, b)  less and even
1 >= 1    	# True    ge(a, b)  greater and even

 

비트(Bitwise) 연산자

5 & 9         	# AND : 0b101 & 0b1001 = 0b0001 (1)         and_(a, b)
5 | 9         	# OR  : 0b101 | 0b1001 = 0b1101(13)         or_(a, b)
5 ^ 9         	# XOR : 0b101 ^ 0b1001 = 0b1100(12)         xor(a, b)
9 << 1         	# left shift  : 0b1001 << = 0b10010(18)     lshift(a, b)
9 >> 1         	# right shift : 0b1001 >> = 0b  100 (4)     rshift(a, b)
~9             	# inversion 0b....1001 = 0b11..10110(-10)   invert(a)

 

할당(Assignment) 연산자. 산술연산자, 비트연산자 뒤에 =을 붙이면 연산한 뒤, 변수에 그대로 할당된다.

a = 11
a =+ 2  	# 13

 

논리(Logical) 연산자

a = 1000
b = 1000
a is b         	# False   is_(a, b)
a is not b     	# True    is_not(a, b)

c = 1000
d = c          	# 얕은 복사 (shallow copy)
c is d        	# True    is_(a, b)

e = True
not e         	# False   not_(a)

 

시퀀스(Sequence) 관련 연산자

a = [1, 2]
b = [3, 4]
1 in a      # True                contains(seq, obj)
a + b       # [1, 2, 3, 4]    concat(seq1, seq2)     seq끼리는 덧셈이 concat으로 동작.
a * 2       # [1, 2, 1, 2]    concat(seq1, seq2)*2   concat 반복동작.

* seq에서 + 연산자는 broadcasting 동작이 아닌 concat으로 동작한다. 이렇게 연산되는 객체가 다른 Type을 가질 경우, 동작을 다르게 하는 경우가 있다. 다른 연산자는 동작하지 않는다.

 

>>> a = [1, 2]
>>> b = [3, 4]
>>> b - a	     # seq에 대해서 a - b 동작은 정의가 안되어 있다.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'list' and 'list'

* numpy array를 위한 행렬 곱 연산자로 "@"를 사용할 수 있지만 이 얘기는 numpy에서 다루도록 하겠습니다.

 

 


변수 선언(Declaring a variable)

python은 변수를 선언할 때 형식을 미리 지정하지 않고, 값에 따라 변수의 데이터 타입을 자동으로 정합니다. 이를 동적 타입핑(Dynamic Typing)이라 합니다.

>>> a = 1
>>> type(a)         # type은 변수의 형식을 알아내는 함수이다.
<class 'int'>
>>> a = 1.1         # int(정수) 변수에 float(소수) 변수값을 대입했다.
>>> type(a)
<class 'float'>     # float로 출력되는 것을 볼 수 있다.

 

 

C언어나 Java를 하신 분이라면 위와 같은 예시는 꿈도 못꿀 예시입니다. 이전 프로그래밍에서는 변수는 Type이 미리 지정이 되어야 하고, Type이 변경되면, 꼭 어떤 Type으로 변경할 지 명시 해야 합니다. 

/**
 * C++ code에서 변수 선언 예시
 */
int a = 1;              // int 형식의 a 변수 선언
vector<float> b = {};   // vector<float> 형식의 b 선언.
b.push_back((float)a);  // a를 float로 type 변경 후 b에 삽입.

cout << b[0] << endl;   // 1 출력

 

하지만 Python은 Type을 변수의 값에 맞춰 스스로 변경합니다. 이런 방법은 개발자의 편의성을 증대시키지만, 개발자 스스로에게 책임감있는 행동을 강요합니다. 데이터 type을 제대로 관리하지 않으면 다음과 같은 사고가 발생할 수 있습니다.

>>> a = [1, 2, 3]   # a를 list로 선언
>>> a == True       # 누군가가 a가 bool type으로 생각해 True와 비교함.
False               # a는 False구나....라는 오해가 생김.

 

위의 예시는 매우 짧은 코드이므로, 실제로 저런 상황은 발생하지 않을 것입니다. 하지만 만약, 10000줄이 넘어가는 코드라면 어떨까요? 이러한 문제를 방지하기 위해 Python은 Type hints를 지원합니다.

a: int = 10    ## int type의 변수라는 hint

 

하지만 hint는 hint일 뿐, 강제되는 사항은아니고, hint를 어긴다고 프로그램이 종료되지는 않습니다. 그래도 개발하는 과정을 좀 더 명확히 해주기 때문에, 중요한 부분은 작성하면 좋을 듯 합니다.

 

 


조건문(Conditional statements)

python의 조건문은 가독성이 매우 뛰어납니다.

checked = True

if checked == True:
    print("it is checked")
elif checked == False:
    print("it is not checked")
else:
    print("Not predicted value")

 

python의 if문이 특이한 점은 다음과 같습니다.

1. if 키워드 후에 괄호( )를 사용하지 않음

2. ":"로 if 문을 마무리

3. if문 조건성립 시 실행할 구문을 중괄호{ }가 아닌 4칸 띄어서 표현

4. if문이 끝나고 다음 조건을 elif, else 키워드 활용

 

덕분에 괄호 지옥에서 벗어나 깔끔한 코드 작성을 할 수 있게 되었습니다.

 

심지어 flag를 bool type으로 비교하므로 ==을 is로 바꿔서 사용해도 됩니다.

checked = True

if checked:
    print("it is checked")
elif checked is False:
    print("it is not checked")
else:
    print("Not predicted value")

 

가독성을 추구하는 python 답게, if문 작성이 매우 쉽고 보기 편합니다. 참고로 C++의 if문은 다음과 같습니다.

bool checked = true;

if(checked) {
    cout << "a is checked" << endl;
} else if(checked == false) {
    cout << "a is not checked" << endl;
} else {
    cout << "not predict value" << endl;
}

 

 


반복문(looping statements)

python에는 반복문에는 for문while문 2가지가 있습니다. 이 2가지 반복문 또한 블럭 단위를 { }로 표현하지 않고 있습니다. 

 

1. 몇 번 반복할 지, 혹은 어떤 나열을 확인할 지 정확히 알고 있음 : for문 사용하기

a = [1, 2, 3, 4, 5, 6]
for i in range(len(a)): 	## a 길이만큼 반복
    a[i] *= 2
print(a)     # 2, 4, 6, 8, 10, 12

python에서는 for(i = 0; i < size ; i++) 와 같은 for문이 없습니다. 대신 for i in range(number)로 대체되었습니다.

range는 Sequence 타입입니다. 만약 range 대신 다른 Sequence Type을 사용해도 for문은 돌아갑니다.

 

a = [1, 2, 3, 4, 5, 6]
b = []
for a_element in a:  		## a의 원소를 a_element라 칭하며, a의 원소 개수만큼 반복
    b.append(a_element * 2)
print(b)     # 2, 4, 6, 8, 10, 12

 

 

2. 반복횟수가 명확하진 않지만, 어떤 조건에 반복이 끝날 지 알고 있음 : while문 사용하기.

a = [1, 2, 3, 4, 5, 6]
b = []
index = 0

## index가 a길이보다 작으면서, a[index]가 5보다 작을 때까지 반복
while len(a) > index and a[index] < 5:	
    b.append(a[index]*2)
    index += 1         		## index를 증가하여, 무한반복에 빠지지 않게 한다.
print(b)    # 2, 4, 6, 8

 

조건이 잘못 설정되는 경우 무한 loop를 돌 수 있습니다. while문이 반드시 필요한 것이 아니라면, for문을 되도록 사용하도록 합시다.

 

 


함수(Function)

함수는 def 키워드와 return를 사용합니다. 함수를 여기에서 설명하기에는 너무 내용이 길어져 간단한 형식만 남깁니다.

def add2(number):
    return number + 2

def no_return_function(number):
    number = 0

def add_numbers(num1, num2):
    return num1+num2;

print(add2(3))                	# 5
print(no_return_function(5))	# None
print(add_numbers(10, 12))    	# 22

 

 


클래스(Class)

class는 class 키워드, self로 변수참조와, __init__등 magic method가 존재합니다. 클래스를 여기에서 설명하기에는 너무 내용이 길어져 간단한 형식만 남깁니다.

class Car:
    price = 10
    def __init__(self, model):
        self.model = model
    
    def model_change(self, change_model):
        self.model = change_model
    
    def get_model(self):
        return self.model
    
    def get_price(self):
        return self.price

 

 

 

 


* reference

https://docs.python.org/3/library/typing.html

https://docs.python.org/3/library/operator.html

https://docs.python.org/3/library/stdtypes.html

'Python > Basic' 카테고리의 다른 글

Python - List Comprehension  (0) 2023.03.19
Python - Int의 크기가 28bytes인 이유  (5) 2023.03.01
Python - Mutable vs Immutable  (2) 2023.02.26
Python - List는 어떻게 데이터를 관리하는가?  (0) 2023.02.15
Python - is와 ==의 차이  (1) 2023.02.10