# Procedural
import string
myStr = ' contain whitespace '
myStr = string.strip(myStr)
# Object-Oriented
myStr = ' contain whitespace '
myStr = myStr.strip()
# 클래스 템플릿
class c(object):
def __init__(self, arg):
super(c, self).__init__()
self.arg = arg
print(arg)
c = c('ok')
결과)
ok
- 클래스를 변수에 할당함 = 클래스의 실체화 = 인스턴스 생성 = 메모리에 클래스를 적재
- 클래스는 변수와 함수를 한 컨테이너에 담은 것
- 하나의 클래스를 이용해 다수의 객체를 생성할 수 있으므로 각각의 객체를 구분하기 위해서 클래스에 self를 사용한다. 이 self의 의미는 이번에 내가 생성한 객체 바로 그것을 나타낸다. 최초 생성될 때는 내용은 같지만 메모리 내에는 구분된 다른 공간들을 차지 하고 있으므로 차지하고 있는 공간 각각을 가리킨다고 이해할 수도 있다. 또 클래스의 모양으로는 변수명이 동일하므로 서로 다른 객체의 같은 변수명이 차지하고 있기 때문에 self가 달라지면 그 변수 또한 다른 것을 의미하도록 self가 역할을 한다고도 볼 수 있다.
- 클래스 내의 변수는 필드 함수는 메쏘드로 부르며, 필드 + 메쏘드 = 속성이라 한다.
- 필드는 또 다시 두 가지로 나뉘어 지는데, 클래스 변수와 객체 변수이다. 클래스에서 여러 개의 객체가 탄생한다고 했으니 클래스 변수는 단 하나이며 객체 변수는 여러 개가 가능하다. 객체의 모태가 클래스이므로 클래스 변수가 바뀌면 여러 객체들에서도 클래스 변수는 다 변경된 상태이다. 하지만 객체 변수는 객체마다 가지고 있으므로 (self의 존재가 그것을 증명한다) 객체 변수 개개는 서로 다른 값을 가질 수 있다.
- Class: A Blueprint for an object
- Object: An Instance of a class
- A Class consists of data and Actions (Variables & Methods)
- Two types Data: Class Variables & Instance Variables
- Class Variables and Methods are shared by all objects of a class
- Instance Variables are within the object space and accessible only to that object
- Encapsulation: Packaging of Data Variables and action methods is called encapsulation
- Inheritance: Classes can be extended (both attributes and functionality) by creating derived classes using all the properties of base (super) class
- Multiple Inheritance: Creating classes using more than one base class. Python supports multiple Inheritance
- Methods Overriding: A base class method can be changed or extended in a derived class
- Objects
- The name for "a thing"
- An object is instantiated (created) from a class
- Classes
- The blueprint for an object; declaring what the thing has and what the thing does
- Attributes
- What the thing has
- Methods
- What the thing does; these are no different from subroutines (at procedural programming)
- Concepts
- Behavior is created by object interaction (a.k.a message passing)
- Objects are interacted with via their methods
- Objects contain state (data) via theit attributes
# 속성을 가진 클래스를 정의한다.
class House:
doors = 1
# 클래스에서 객체를 만든 후 속성을 읽어온다.
class House:
doors = 1
myHouse = House()
print(myHouse.doors)
결과)
1
# 객체의 속성에 쓰기를 한다.
class House:
doors = 1
myHouse = House()
myHouse.doors = 4print(myHouse.doors)
결과)
4
# 객체에 속성을 읽기하는 메쏘드를 추가한다.
class House:
doors = 1
def openDoors(self):
for door in range(self.doors):
print('door opened.')
myHouse = House()
myHouse.doors = 4myHouse.openDoors()
결과)
door opened.
door opened.
door opened.
door opened.
# 객체에 속성 쓰기하는 메쏘드를 추가한다.
class House:
doors = 1
def openDoors(self):
for door in range(self.doors):
print('door opened.')
def addDoors(self, number):
self.doors += number
myHouse = House()
myHouse.doors = 4
myHouse.addDoors(1)myHouse.openDoors()
결과)
door opened.
door opened.
door opened.
door opened.
door opened.
# 초기화 메쏘드의 추가
class House:
def __init__(self, doors):
self.doors = doors
def openDoors(self):
for door in range(self.doors):
print('door opened.')
myHouse = House(doors = 4)
myHouse.openDoors()
결과)
door opened.
door opened.
door opened.
door opened.
# 클래스의 상속
class House:
def __init__(self, doors):
self.doors = doors
def openDoors(self):
for door in range(self.doors):
print('door opened.')
class Villa(House):
pass
myHouse = Villa(doors = 4)
myHouse.openDoors()
결과)
door opened.
door opened.
door opened.
door opened.
# 상속 클래스에 추가된 메쏘드 사용
class House:
def __init__(self, doors):
self.doors = doors
def openDoors(self):
for door in range(self.doors):
print('door opened.')
class Villa(House):
swimpool = True
def readyToSwim(self):
if self.swimpool:
print('You can swimming.')
else:
print('You can not swimming now.')
myHouse = Villa(doors = 4)
myHouse.openDoors()
myHouse.readyToSwim()
결과)
door opened.
door opened.
door opened.
door opened.
You can swimming.
# 상속 클래스에서 부모 클래스와 동일한 메쏘드 이름을 사용할 수 있음
class House:
def __init__(self, doors):
self.doors = doors
def openDoors(self):
for door in range(self.doors):
print('door opened.')
class Villa(House):
swimpool = Truedef readyToSwim(self):
if self.swimpool:
print('You can swimming.')
else:
print('You can not swimming now.')
def paintingOutside(self):
print('Your villa applied new paintings.')
class Apartment(House):
def paintingOutside(self):
print('Your apartment applied new paintings.')
myBuildings = [Villa(doors=1), Apartment(doors=2)]
for mb in myBuildings:
mb.paintingOutside()
결과)
Your villa applied new paintings.
Your apartment applied new paintings.
# 다형성 - 상속된 객체에 있는 메쏘드를 동일한 방식으로 호출할 수 있다.
class Characters():
def display(self):
print('Parent display.')
class String(Characters):
def display(self):
print('String display.')
class Number(Characters):
def display(self):
print('Number display.')
c = Characters()
s = String()
n = Number()
for o in (c, s, n):
o.display()
결과)
Parent display.
String display.
Number display.
# 다형성 - 객체에 알맞는 메쏘드만 실행한다.
class Characters():
def display(self):
print('Parent display.')
class String(Characters):
def display(self):
print('String display.')
def lower(self):
print('String lowered.')
def double(self):
return
class Number(Characters):
def display(self):
print('Number display.')
def lower(self):
return
def double(self):
print('Number is doubled.')
s = String()
n = Number()
for o in (s, n):
o.display()
o.lower()
o.double()
결과)
String display.
String lowered.
Number display.
Number is doubled.
# 상속 객체에 없는 메쏘드는 부모 객체에서 찾는다.
class P():
def walk(self):
print('walking.')
class C(P):
def crawl(self):
print('crawling.')
c = C()
c.crawl()
c.walk()
결과)
crawling.
walking.
# 클래스의 인스턴스를 생성할때 인자가 맞지 않으면 실패한다.
class Person():
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
def getName(self):
return self.name
def getAge(self):
return self.age
def getAddress(self):
return self.address
noArgs = Person()
결과)
TypeError: __init__() missing 3 required positional arguments: 'name', 'age', and 'address'
# 함수의 인자와 마찬가지로 default 인자를 줄 수 있다.
class Person():
def __init__(self, name='noname', age=None, address=None):
self.name = name
self.age = age
self.address = address
def getName(self):
return self.name
def getAge(self):
return self.age
def getAddress(self):
return self.address
defaultArgs = Person()
currentName = defaultArgs.getName()
print(currentName)
결과)
noname
# 객체의 필드를 직접 수정할 수 있다.
class Person():
def __init__(self, name='noname', age=None, address=None):
self.name = name
self.age = age
self.address = address
def getName(self):
return self.name
def getAge(self):
return self.age
def getAddress(self):
return self.address
defaultArgs = Person()
defaultArgs.name = 'mike'
currentName = defaultArgs.getName()
print(currentName)
결과)
mike
# 두 개의 언더스코어를 붙이면 외부에서 직접 액세스 할 수 없다.
class Person():
def __init__(self, name='noname', age=None, address=None):
self.__name = name
self.__age = age
self.__address = address
def getName(self):
return self.__name
def getAge(self):
return self.__age
def getAddress(self):
return self.__address
defaultArgs = Person()
defaultArgs._name = 'mike'
currentName = defaultArgs.getName()
print(currentName)
결과)
noname
# kwargs와 getter/setter 메쏘드를 이용해서 flexiable한 코드가 가능하다.
class Animal:
def __init__(self, **kwargs):
self.variables = kwargs
def setVariable(self, k, v):
self.variables[k] = v
def getVariable(self, k):
return self.variables.get(k, None)
a = Animal(color = 'white')
a.setVariable('height', 2)
print(a.getVariable('color'))
print(a.getVariable('height'))
결과)
white
2
# 클래스 변수와 마찬가지 의미로 클래스 메쏘드가 가능하다. 의미상 클래스의 객체가 만들어지지 않은 상황에서 메소드가 필요할 때 사용할 수 있으며 관례상 self 자리에 cls로 표기한다.
class Item():
def __init__(self, color, size):
self.color = color
self.size = size
def display(self):
print('color: ' + self.color, 'size: ' + self.size)
@classmethod
def createItem(cls, itemlist):
for color, size in itemlist:
yield cls(color, size)
items = ('yellow', 'middle'), ('black', 'small')
for i in Item.createItem(items):
i.display()
결과)
color: yellow size: middle
color: black size: small
# 스태택 메쏘드는 클래스 메쏘드와 유사한 성질을 가지지만 객체를 인자로 받지 않는다. 클래스 메쏘드와 비교할 때 같은 일을 하는데 있어 명시적으로 클래스 이름을 적어야 하는 면에서 차이가 있다.
class Item():
def __init__(self, color, size):
self.color = color
self.size = size
def display(self):
print('color: ' + self.color, 'size: ' + self.size)
@staticmethod
def createItem(itemlist):
for color, size in itemlist:
yield Item(color, size)
items = ('yellow', 'middle'), ('black', 'small')
for i in Item.createItem(items):
i.display()
결과)
color: yellow size: middle
color: black size: small
# 데코레이터를 사용한 프로퍼티 세팅/게팅
class Thing():
def __init__(self, **kwargs):
self._properties = kwargs
@property
def color(self):
return self._properties.get('color', None)
@color.setter
def color(self, c):
self._properties['color'] = c
@color.deleter
def color(self):
del self._properties['color']
t = Thing()
t.color = 'white'
print(t.color)
결과)
white
# 자식 클래스에서는 부모 클래스의 속성을 이어 받을 수 있다. 이러한 상속 관계를 가지기 때문에 부모 클래스의 변경 사항 한 번으로 이를 상속받은 자식 클래스에 바로 변경이 반영될 수 있다. 또한 같은 이름의 메쏘드라도 자식 클래스 마다 각각 다르게 정의할 수 있어서 코딩을 간편하게 유지할 수 있다.
class Transport():
def __init__(self, name):
self.name = name
def display(self):
print('Name: ' + self.name)
class Bicycle(Transport):
def __init__(self, name, wheel):
super().__init__(name)
self.wheel = wheel
def display(self):
super().display()
print('Wheel: ', self.wheel)
class Car(Transport):
def __init__(self, name, fair):
super().__init__(name)
self.fair = fair
def display(self):
super().display()
print('Fair: ', self.fair)
b = Bicycle('Bicycle', 2)
c = Car('Car', 1000)
b.display()
c.display()
결과)
Name: Bicycle
Wheel: 2
Name: Car
Fair: 1000
# to-string 메소드 재정의를 통한 클래스 출력
# __str__ 메소드 재정의
class Name:
def __init__(self, p1, p2, p3):
self.p1 = p1
self.p2 = p2
self.p3 = p3
def __str__(self):
return self.p1 + ' ' + self.p2 + ' ' + self.p3
def initials(self):
return self.p1[0] + self.p2[0] + self.p3[0]
aPerson = Name('mike', 'jane', 'peggy')
print(aPerson)
print(aPerson.initials())
결과)
mike jane peggy
mjp
# 클래스의 필드, 메쏘드를 이용한 클래스의 이해
class Student:
# 클래스 필드 정의
grades = []
# 인스턴스 필드 정의
def __init__(self, name, id):
self.name = name
self.id = id
# 인스턴스 메쏘드로 클래스 필드에 값을 추가한다.
def addGrade(self, grade):
self.grades.append(grade)
# 인스턴스 메쏘드로 새로운 값을 반환한다.
def showGrades(self):
grds = ''
for grade in self.grades:
grds += str(grade) + ' '
return grds
# 인스턴스 필드와 메쏘드에 접근한다.
def __str__(self):
return 'Name: ' + self.name + '\n' + \
'Id: ' + self.id + '\n' + \
'Grades: ' + self.showGrades() + '\n' + \
'Average: ' + str(self.getAverage())
# 클래스 필드에 접근해서 계산값을 반환한다.
def getAverage(self):
total = 0
for grade in self.grades:
total += grade
return total / len(self.grades)
s1 = Student('mike', '112')
s1.addGrade(45)
s1.addGrade(80)
s1.addGrade(68)
print(s1)
결과)
Name: mike
Id: 112
Grades: 45 80 68
Average: 64.33333333333333
# getattr, setattr, hasattr
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('mike', 22)
n = getattr(p, "name")
print(n)
setattr(p, "name", "jane")
n = getattr(p, "name")
print(n)
h = hasattr(p, "name")
print(h)
결과)
mike
jane
True
"""
Polymorphism
- The third pillar of OOP
- Two classes with samen interface (i.e., method name)
- The methods are often different, but conceptually similar
- Allows for expressiveness in design: we can say that
this group of related classes implement the same action
- Duck typing refers to reading an object's attributes to decide
whether it is of a proper type, rather than checking the
type itself
"""
"""
Inheritance Examples
- When working in a child class we can choose to
implement parent class methods in different ways
- inherit: simply use the parent class' defined
method
- Override/overload: provide child's own version
of a method
- Extend: do work in addition to that in parent's
method
- Provide: implement abstract method that parent
requires
"""
"""
Composition vs. Inheritance
- Inheritance can be brittle (a change may require
changes elsewhere)
- Decoupled code is classes, functions, etc. that
work independently and don't depend on one another
- As long as the interface is maintained, interactions
between classes will work
- Not checking or requiring particular types is
polymorphic and Pythonic
"""
# Implementing Core Syntax
class MaxList():
def __init__(self, this_list):
self.mylist = this_list
def __add__(self, other):
new_list = [max(x, y) for x, y in zip(self.mylist, other.mylist)]
return MaxList(new_list)
def __repr__(self):
return str(self.mylist)
cc = MaxList([1, 2, 3, 4, 5])
dd = MaxList([5, 4, 3, 2, 1])
ee = cc + dd
print(ee)
# 결과
[5, 4, 3, 4, 5]
# Subclassing - dict
class MyDict(dict):
def __setitem__(self, key, val):
print("setting a key and value.")
dict.__setitem__(self, key, val)
dd = MyDict()
dd['a'] = 5
dd['6'] = 6
for key in dd.keys():
print('{} = {}'.format(key, dd[key]))
# 결과
setting a key and value.
setting a key and value.
6 = 6
a = 5
# class를 사용해서 두 리스트의 합을 가진 새로운 리스트를 리턴
class PlusList():
def __init__(self, this_list):
self.mylist = this_list
def __add__(self, other):
new_list = [x + y for x, y in zip(self.mylist, other.mylist)]
return PlusList(new_list)
def __repr__(self):
return str(self.mylist)
a = PlusList([1, 2])
b = PlusList([1, 1])
c = a + b
print(c)
# 결과
[2, 3]
# BO(Business Object), Data, UI로 분리해서 구현한 두 개 리스트의 합 리턴
class Data():
def __init__(self, list):
self.this_list = list
def get_data(self):
return self.this_list
class Calc():
def __init__(self, one, two):
self.one = one
self.two = two
def plus(self):
new_list = [x + y for x, y in zip(self.one.get_data(), self.two.get_data())]
return new_list
class UI():
def __init__(self):
self.one = Data([1, 2])
self.two = Data([1, 1])
self.calc = Calc(self.one, self.two)
def get_calc(self):
return self.calc.plus()
def get_one(self):
return self.one.get_data()
def get_two(self):
return self.two.get_data()
u = UI()
print(u.get_calc())
# 결과
[2, 3]
댓글 영역