Last active
June 6, 2018 02:47
-
-
Save domodomodomo/81088da7af8e71493c75caeea786b380 to your computer and use it in GitHub Desktop.
Emulating Object Oriented Programming with dict and function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Emulating Object Oriented Programming with dict and function. | |
### 0. reference | |
1) This code was written by refering below content. | |
Python のクラスシステム - http://www.shido.info/py/python7.html | |
### 1. emulating 3 concepts, class, instance and method. | |
1) class -> dict | |
2) instance -> dict | |
3) method -> function | |
### 2. emulating 3 built-in functions. | |
1) setattr -> setattr_ | |
2) getattr -> getattr_ | |
3) type -> type_ | |
https://docs.python.jp/3/library/functions.html#type | |
https://docs.python.jp/3/library/functions.html#setattr | |
https://docs.python.jp/3/library/functions.html#getattr | |
### 3. creating 1 new function for convinience. | |
1) instantiate -> instantiate_ | |
### 4. consideration | |
The complexity of getattr_() function in this code shows | |
that attribue reference is one of the most important factor | |
in object oriented programming language. | |
""" | |
# | |
# | |
# | |
def main(): | |
print('### 0. You have got two same results.') | |
print() | |
print('### 1. instance object') | |
print(' executing with builtin functions') | |
sample_code(setattr, getattr, type, instantiate) | |
print() | |
print('### 2. emulating dict object') | |
print(' executing with emulating functions') | |
sample_code(setattr_, getattr_, type_, instantiate_) | |
print() | |
# | |
# | |
# | |
def sample_code(setattr, getattr, type, instantiate): | |
# | |
# 1. Define class. | |
# | |
def __init__(self, name, task): | |
setattr(self, 'name', name) | |
setattr(self, 'task', task) | |
def work(self, hour): | |
name = getattr(self, 'name') | |
task = getattr(self, 'task') | |
max_hour = getattr(self, 'max_hour') | |
return '%s %s for %d hours of %d hours.'\ | |
% (name, task, hour, max_hour) | |
ItWorker = type( | |
'ItWorker', | |
(object, ), | |
{'max_hour': 7, '__init__': __init__, 'work': work} | |
) | |
# | |
# 2. Instantiate object. | |
# | |
henley = instantiate(ItWorker, 'Henley', 'makes web site') | |
thomas = instantiate(ItWorker, 'Thomas', task='checks up server') | |
gates = instantiate(ItWorker, name='Gates', task='writes programs') | |
# | |
# 3. | |
# | |
print('# (1) Refer instance attributes.') | |
print(getattr(henley, 'max_hour')) | |
print(getattr(thomas, 'name')) | |
print(getattr(gates, 'task')) | |
print('# (2) Overwrite instance attributes.') | |
setattr(henley, 'max_hour', 12) | |
setattr(thomas, 'name', 'James') | |
setattr(gates, 'task', 'desings web page') | |
print(getattr(henley, 'max_hour')) | |
print(getattr(thomas, 'name')) | |
print(getattr(gates, 'task')) | |
print('# (3) Refer class attributes.') | |
# print(getattr(henley, 'max_hour')) # class attribute was overwritten. | |
print(getattr(thomas, 'max_hour')) | |
print(getattr(gates, 'max_hour')) | |
print('# (4) Call methods.') | |
print(getattr(henley, 'work')(3)) | |
print(getattr(thomas, 'work')(4)) | |
print(getattr(gates, 'work')(6)) | |
print('# (5) Change methods dynamically.') | |
def holiday(self, days): | |
name = getattr(self, 'name') | |
return '%s enjoys vacation for %d days' % (name, days) | |
setattr(ItWorker, 'work', holiday) | |
print(getattr(henley, 'work')(3)) | |
print(getattr(thomas, 'work')(4)) | |
print(getattr(gates, 'work')(6)) | |
def instantiate(cls, *args, **kwargs): | |
self = cls(*args, **kwargs) | |
return self | |
# | |
# Using dict and function(closure), | |
# we can emulate instance object, class object and method. | |
# | |
def setattr_(obj: dict, attr_name, value): | |
"""Set a value to the attribute.""" | |
obj[attr_name] = value | |
def getattr_(obj: dict, attr_name): | |
"""Get a value from the attribute.""" | |
# instance attribute | |
if attr_name in obj: | |
value = obj[attr_name] | |
return value | |
# class attribute | |
elif attr_name in obj['__class__']: | |
value = obj['__class__'][attr_name] | |
# value | |
if not callable(value): | |
return value | |
# method | |
else: | |
def method(*args, **kwargs): | |
return value(obj, *args, **kwargs) | |
return method | |
else: | |
raise AttributeError("object has no attribute '%s'" % attr_name) | |
def type_(name: str, bases: tuple, class_name_space: dict) -> dict: | |
"""Create a new class object.""" | |
cls = {} | |
cls['__name__'] = name | |
cls['__bases__'] = bases # inheritance is not implemented. | |
cls.update(class_name_space) | |
return cls | |
def instantiate_(cls: dict, *args, **kwargs) -> dict: | |
"""Create a new instance object.""" | |
self = {} | |
self['__class__'] = cls | |
getattr_(self, '__init__')(*args, **kwargs) | |
return self | |
# | |
# | |
# | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment