diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 98a45f4b..3c612acc 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -2,10 +2,7 @@
-
-
-
@@ -17,13 +14,14 @@
+
-
+
@@ -31,7 +29,7 @@
-
+
@@ -56,23 +54,33 @@
-
-
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -80,48 +88,40 @@
-
-
+
+
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
@@ -155,13 +155,6 @@
@@ -234,8 +234,8 @@
-
+
@@ -243,6 +243,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -283,21 +312,21 @@
-
-
+
+
-
+
-
+
@@ -320,74 +349,74 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
@@ -417,11 +446,11 @@
-
+
-
+
@@ -471,62 +500,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -643,7 +616,6 @@
-
@@ -651,7 +623,6 @@
-
@@ -659,7 +630,6 @@
-
@@ -674,7 +644,6 @@
-
@@ -682,9 +651,6 @@
-
-
-
@@ -692,7 +658,6 @@
-
@@ -700,9 +665,6 @@
-
-
-
@@ -710,9 +672,6 @@
-
-
-
@@ -720,9 +679,6 @@
-
-
-
@@ -730,31 +686,20 @@
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
@@ -764,7 +709,6 @@
-
@@ -776,15 +720,26 @@
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
@@ -792,35 +747,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RL/Basic-DisRL-Demo/Categorical_DQN.py b/RL/Basic-DisRL-Demo/Categorical_DQN.py
new file mode 100644
index 00000000..281a6ddf
--- /dev/null
+++ b/RL/Basic-DisRL-Demo/Categorical_DQN.py
@@ -0,0 +1,120 @@
+import tensorflow as tf
+import numpy as np
+import random
+from collections import deque
+from Config import Categorical_DQN_Config
+from utils import conv, dense
+import math
+
+
+class Categorical_DQN():
+ def __init__(self,env,config):
+ self.sess = tf.InteractiveSession()
+ self.config = config
+ self.v_max = self.config.v_max
+ self.v_min = self.config.v_min
+ self.atoms = self.config.atoms
+
+ self.time_step = 0
+ self.epsilon = self.config.INITIAL_EPSILON
+ self.state_shape = env.observation_space.shape
+ self.action_dim = env.action_space.n
+
+ target_state_shape = [1]
+ target_state_shape.extend(self.state_shape)
+
+ self.state_input = tf.placeholder(tf.float32,target_state_shape)
+ self.action_input = tf.placeholder(tf.int32,[1,1])
+
+ self.m_input = tf.placeholder(tf.float32,[self.atoms])
+
+ self.delta_z = (self.v_max - self.v_min) / (self.atoms - 1)
+ self.z = [self.v_min + i * self.delta_z for i in range(self.atoms)]
+
+ self.build_cate_dqn_net()
+
+ self.saver = tf.train.Saver()
+
+ self.sess.run(tf.global_variables_initializer())
+
+ self.save_model()
+ self.restore_model()
+
+
+
+
+ def build_layers(self, state, action, c_names, units_1, units_2, w_i, b_i, reg=None):
+ with tf.variable_scope('conv1'):
+ conv1 = conv(state, [5, 5, 3, 6], [6], [1, 2, 2, 1], w_i, b_i)
+ with tf.variable_scope('conv2'):
+ conv2 = conv(conv1, [3, 3, 6, 12], [12], [1, 2, 2, 1], w_i, b_i)
+ with tf.variable_scope('flatten'):
+ flatten = tf.contrib.layers.flatten(conv2)
+
+ with tf.variable_scope('dense1'):
+ dense1 = dense(flatten, units_1, [units_1], w_i, b_i)
+ with tf.variable_scope('dense2'):
+ dense2 = dense(dense1, units_2, [units_2], w_i, b_i)
+ with tf.variable_scope('concat'):
+ concatenated = tf.concat([dense2, tf.cast(action, tf.float32)], 1)
+ with tf.variable_scope('dense3'):
+ dense3 = dense(concatenated, self.atoms, [self.atoms], w_i, b_i) # 返回
+ return dense3
+
+ def build_cate_dqn_net(self):
+ with tf.variable_scope('target_net'):
+ c_names = ['target_net_arams',tf.GraphKeys.GLOBAL_VARIABLES]
+ w_i = tf.random_uniform_initializer(-0.1,0.1)
+ b_i = tf.constant_initializer(0.1)
+ self.z_target = self.build_layers(self.state_input,self.action_input,c_names,24,24,w_i,b_i)
+
+ with tf.variable_scope('eval_net'):
+ c_names = ['eval_net_params',tf.GraphKeys.GLOBAL_VARIABLES]
+ w_i = tf.random_uniform_initializer(-0.1,0.1)
+ b_i = tf.constant_initializer(0.1)
+ self.z_eval = self.build_layers(self.state_input,self.action_input,c_names,24,24,w_i,b_i)
+
+
+ self.q_eval = tf.reduce_sum(self.z_eval * self.z)
+ self.q_target = tf.reduce_sum(self.z_target * self.z)
+
+ self.cross_entropy_loss = -tf.reduce_sum(self.m_input * tf.log(self.z_eval))
+
+ self.optimizer = tf.train.AdamOptimizer(self.config.LEARNING_RATE).minimize(self.cross_entropy_loss)
+
+
+
+
+ def train(self,s,r,action,s_,gamma):
+ list_q_ = [self.sess.run(self.q_target,feed_dict={self.state_input:[s_],self.action_input:[[a]]}) for a in range(self.action_dim)]
+ a_ = tf.argmax(list_q_).eval()
+ m = np.zeros(self.atoms)
+ p = self.sess.run(self.z_target,feed_dict = {self.state_input:[s_],self.action_input:[[a_]]})[0]
+ for j in range(self.atoms):
+ Tz = min(self.v_max,max(self.v_min,r+gamma * self.z[j]))
+ bj = (Tz - self.v_min) / self.delta_z # 分在第几个块里
+ l,u = math.floor(bj),math.ceil(bj) # 上下界
+
+ pj = p[j]
+
+ m[int(l)] += pj * (u - bj)
+ m[int(u)] += pj * (bj - l)
+
+ self.sess.run(self.optimizer,feed_dict={self.state_input:[s] , self.action_input:[action], self.m_input: m })
+
+
+
+ def save_model(self):
+ print("Model saved in : ", self.saver.save(self.sess, self.config.MODEL_PATH))
+
+ def restore_model(self):
+ self.saver.restore(self.sess, self.config.MODEL_PATH)
+ print("Model restored.")
+
+
+ def greedy_action(self,s):
+ self.epsilon = max(self.config.FINAL_EPSILON, self.epsilon * self.config.EPSILIN_DECAY)
+ if random.random() <= self.epsilon:
+ return random.randint(0, self.action_dim - 1)
+ return np.argmax(
+ [self.sess.run(self.q_target,feed_dict={self.state_input:[s],self.action_input:[[a]]}) for a in range(self.action_dim)])
diff --git a/RL/Basic-DisRL-Demo/Config.py b/RL/Basic-DisRL-Demo/Config.py
new file mode 100644
index 00000000..36495f52
--- /dev/null
+++ b/RL/Basic-DisRL-Demo/Config.py
@@ -0,0 +1,22 @@
+class Categorical_DQN_Config():
+ v_min = 0
+ v_max = 1000
+ atoms = 51
+
+ # ENV_NAME = "CartPole-v1"
+ ENV_NAME = 'Breakout-v0' # 0: hold 1: throw the ball 2: move right 3: move left
+ # ENV_NAME = "Freeway-v0"
+ GAMMA = 0.99 # discount factor for target Q
+ START_TRAINING = 1000 # experience replay buffer size
+ BATCH_SIZE = 64 # size of minibatch
+ UPDATE_TARGET_NET = 400 # update eval_network params every 200 steps
+ LEARNING_RATE = 0.01
+ MODEL_PATH = './model/C51DQN_model'
+
+ INITIAL_EPSILON = 0.9 # starting value of epsilon
+ FINAL_EPSILON = 0.05 # final value of epsilon
+ EPSILIN_DECAY = 0.9999
+
+ replay_buffer_size = 2000
+ iteration = 5
+ episode = 300 # 300 games per iteration
diff --git a/RL/Basic-DisRL-Demo/main.py b/RL/Basic-DisRL-Demo/main.py
new file mode 100644
index 00000000..dfa36cf7
--- /dev/null
+++ b/RL/Basic-DisRL-Demo/main.py
@@ -0,0 +1,65 @@
+
+import matplotlib.pyplot as plt
+import tensorflow as tf
+import gym
+import numpy as np
+import pickle
+from Config import Categorical_DQN_Config
+from Categorical_DQN import Categorical_DQN
+
+
+def map_scores(dqfd_scores=None, ddqn_scores=None, xlabel=None, ylabel=None):
+ if dqfd_scores is not None:
+ plt.plot(dqfd_scores, 'r')
+ if ddqn_scores is not None:
+ plt.plot(ddqn_scores, 'b')
+ if xlabel is not None:
+ plt.xlabel(xlabel)
+ if ylabel is not None:
+ plt.ylabel(ylabel)
+ plt.show()
+
+def BreakOut_CDQN(index, env):
+ with tf.variable_scope('DQfD_' + str(index)):
+ agent = Categorical_DQN(env, Categorical_DQN_Config())
+ scores = []
+ for e in range(Categorical_DQN_Config.episode):
+ done = False
+ score = 0 # sum of reward in one episode
+ state = env.reset()
+ # while done is False:
+ last_lives = 5
+ throw = True
+ items_buffer = []
+ while not done:
+ env.render()
+ action = 1 if throw else agent.greedy_action(state)
+ next_state, real_reward, done, info = env.step(action)
+ lives = info['ale.lives']
+ train_reward = 1 if throw else -1 if lives < last_lives else real_reward
+ score += real_reward
+ throw = lives < last_lives
+ last_lives = lives
+ # agent.train(state, train_reward, [action], next_state, 0.1)
+ items_buffer.append([state, [action], next_state, 0.1])
+ state = next_state
+ if train_reward != 0: # train when miss the ball or score or throw the ball in the beginning
+ for item in items_buffer:
+ agent.train(item[0], -1 if throw else train_reward, item[1], item[2], item[3])
+ items_buffer = []
+ scores.append(score)
+ agent.save_model()
+ # if np.mean(scores[-min(10, len(scores)):]) > 495:
+ # break
+ return scores
+
+
+if __name__ == '__main__':
+ env = gym.make("Breakout-v0")
+ CDQN_sum_scores = np.zeros(Categorical_DQN_Config.episode)
+ for i in range(Categorical_DQN_Config.iteration):
+ scores = BreakOut_CDQN(i,env)
+ c51_sum_scores = [a + b for a, b in zip(scores, CDQN_sum_scores)]
+ C51DQN_mean_scores = CDQN_sum_scores / Categorical_DQN_Config.iteration
+ with open('/Users/mahailong/C51DQN/C51DQN_mean_scores.p', 'wb') as f:
+ pickle.dump(C51DQN_mean_scores, f, protocol=2)
\ No newline at end of file
diff --git a/RL/Basic-DisRL-Demo/readme b/RL/Basic-DisRL-Demo/readme
new file mode 100644
index 00000000..2562e4fd
--- /dev/null
+++ b/RL/Basic-DisRL-Demo/readme
@@ -0,0 +1,2 @@
+论文:A Distributional Perspective on Reinforcement Learning
+地址:https://arxiv.org/abs/1707.06887
\ No newline at end of file
diff --git a/RL/Basic-DisRL-Demo/utils.py b/RL/Basic-DisRL-Demo/utils.py
new file mode 100644
index 00000000..339ebdfb
--- /dev/null
+++ b/RL/Basic-DisRL-Demo/utils.py
@@ -0,0 +1,35 @@
+import tensorflow as tf
+from tensorflow.python.framework import ops
+
+
+def conv(inputs, kernel_shape, bias_shape, strides, w_i, b_i=None, activation=tf.nn.relu):
+ # 使用tf.layers
+ # relu1 = tf.layers.conv2d(input_imgs, filters=24, kernel_size=[5, 5], strides=[2, 2],
+ # padding='SAME', activation=tf.nn.relu,
+ # kernel_initializer=w_i, bias_initializer=b_i)
+ weights = tf.get_variable('weights', shape=kernel_shape, initializer=w_i)
+ conv = tf.nn.conv2d(inputs, weights, strides=strides, padding='SAME')
+ if bias_shape is not None:
+ biases = tf.get_variable('biases', shape=bias_shape, initializer=b_i)
+ return activation(conv + biases) if activation is not None else conv + biases
+ return activation(conv) if activation is not None else conv
+
+
+def dense(inputs, units, bias_shape, w_i, b_i=None, activation=tf.nn.relu):
+ # 使用tf.layers,注意:先flatten
+ # dense1 = tf.layers.dense(tf.contrib.layers.flatten(relu5), activation=tf.nn.relu, units=50)
+ if not isinstance(inputs, ops.Tensor):
+ inputs = ops.convert_to_tensor(inputs, dtype='float')
+ # dim_list = inputs.get_shape().as_list()
+ # flatten_shape = dim_list[1] if len(dim_list) <= 2 else reduce(lambda x, y: x * y, dim_list[1:])
+ # reshaped = tf.reshape(inputs, [dim_list[0], flatten_shape])
+ if len(inputs.shape) > 2:
+ inputs = tf.contrib.layers.flatten(inputs)
+ flatten_shape = inputs.shape[1]
+ weights = tf.get_variable('weights', shape=[flatten_shape, units], initializer=w_i)
+ dense = tf.matmul(inputs, weights)
+ if bias_shape is not None:
+ assert bias_shape[0] == units
+ biases = tf.get_variable('biases', shape=bias_shape, initializer=b_i)
+ return activation(dense + biases) if activation is not None else dense + biases
+ return activation(dense) if activation is not None else dense
\ No newline at end of file
diff --git a/basic/.ipynb_checkpoints/class_and_instance-checkpoint.ipynb b/basic/.ipynb_checkpoints/class_and_instance-checkpoint.ipynb
new file mode 100644
index 00000000..2fd64429
--- /dev/null
+++ b/basic/.ipynb_checkpoints/class_and_instance-checkpoint.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/basic/class_and_instance.ipynb b/basic/class_and_instance.ipynb
new file mode 100644
index 00000000..dccf6fd3
--- /dev/null
+++ b/basic/class_and_instance.ipynb
@@ -0,0 +1,1031 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "dog = Animal('hasky',90)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "90\n",
+ "100\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(dog.weight) #90\n",
+ "dog.weight = 100\n",
+ "print(dog.weight) #100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "hasky : 90\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ "\n",
+ "dog = Animal('hasky',90)\n",
+ "dog.print_weight() # hasky : 90"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "hasky\n"
+ ]
+ },
+ {
+ "ename": "AttributeError",
+ "evalue": "'Animal' object has no attribute '__name'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0mdog\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'hasky'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m90\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdog\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# hasky\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 18\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdog\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 'Animal' object has no attribute '__name'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 19\u001b[0m \u001b[0mdog\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdog\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 100\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mAttributeError\u001b[0m: 'Animal' object has no attribute '__name'"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.__name = name\n",
+ " self.__weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ " def get_name(self):\n",
+ " return self.__name\n",
+ " def get_weight(self):\n",
+ " return self.__weight\n",
+ " def set_name(self,name):\n",
+ " self.__name = name\n",
+ " def set_weight(self,weight):\n",
+ " self.__weight = weight\n",
+ "\n",
+ "dog = Animal('hasky',90)\n",
+ "print(dog.get_name()) # hasky\n",
+ "print(dog.__name) # AttributeError: 'Animal' object has no attribute '__name'\n",
+ "dog.set_weight(100)\n",
+ "print(dog.get_weight()) # 100\n",
+ "print(dog.__weight) # AttributeError: 'Animal' object has no attribute '__weight'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'_Animal__name': 'hasky', '_Animal__weight': 90}"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dog.__dict__"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Animal is running\n",
+ "Dog is eating\n",
+ "Cat is running\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ " def run(self):\n",
+ " print('Animal is running')\n",
+ "\n",
+ "class Dog(Animal):\n",
+ " def eat(self):\n",
+ " print('Dog is eating')\n",
+ "class Cat(Animal):\n",
+ " def run(self):\n",
+ " print('Cat is running')\n",
+ "\n",
+ "dog = Dog('hasky',10)\n",
+ "dog.run() # Animal is running\n",
+ "dog.eat() # Dog is eating\n",
+ "cat = Cat('tt',20)\n",
+ "cat.run() # Cat is running"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'hasky'"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ " def run(self):\n",
+ " print('Animal is running')\n",
+ "\n",
+ "class Dog(Animal):\n",
+ " def __init__(self,name,weight,height):\n",
+ " super().__init__(name,weight)\n",
+ " self.height = height\n",
+ " def eat(self):\n",
+ " print('Dog is eating')\n",
+ "\n",
+ "dog = Dog('hasky',10,20)\n",
+ "dog.name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n",
+ "True\n",
+ "True\n",
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ " def run(self):\n",
+ " print('Animal is running')\n",
+ "\n",
+ "class Dog(Animal):\n",
+ " def eat(self):\n",
+ " print('Dog is eating')\n",
+ "\n",
+ "a = Dog(\"hasky\",90)\n",
+ "b = Animal('tt',10)\n",
+ "print(isinstance(a,Dog))# True\n",
+ "print(isinstance(a,Animal))# True\n",
+ "print(isinstance(b,Animal))# True\n",
+ "print(isinstance(b,Dog))# False\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Animal is running\n",
+ "Animal is running\n",
+ "Animal is running\n",
+ "Animal is running\n"
+ ]
+ }
+ ],
+ "source": [
+ "def run_twice(obj):\n",
+ " obj.run()\n",
+ " obj.run()\n",
+ "\n",
+ "a = Dog(\"hasky\",90)\n",
+ "b = Animal('tt',10)\n",
+ "run_twice(a)\n",
+ "run_twice(b)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "start....\n",
+ "start....\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Timer(object):\n",
+ " def run(self):\n",
+ " print('start....')\n",
+ "\n",
+ "timer = Timer()\n",
+ "run_twice(timer)\n",
+ "# start....\n",
+ "# start...."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['__add__',\n",
+ " '__class__',\n",
+ " '__contains__',\n",
+ " '__delattr__',\n",
+ " '__dir__',\n",
+ " '__doc__',\n",
+ " '__eq__',\n",
+ " '__format__',\n",
+ " '__ge__',\n",
+ " '__getattribute__',\n",
+ " '__getitem__',\n",
+ " '__getnewargs__',\n",
+ " '__gt__',\n",
+ " '__hash__',\n",
+ " '__init__',\n",
+ " '__init_subclass__',\n",
+ " '__iter__',\n",
+ " '__le__',\n",
+ " '__len__',\n",
+ " '__lt__',\n",
+ " '__mod__',\n",
+ " '__mul__',\n",
+ " '__ne__',\n",
+ " '__new__',\n",
+ " '__reduce__',\n",
+ " '__reduce_ex__',\n",
+ " '__repr__',\n",
+ " '__rmod__',\n",
+ " '__rmul__',\n",
+ " '__setattr__',\n",
+ " '__sizeof__',\n",
+ " '__str__',\n",
+ " '__subclasshook__',\n",
+ " 'capitalize',\n",
+ " 'casefold',\n",
+ " 'center',\n",
+ " 'count',\n",
+ " 'encode',\n",
+ " 'endswith',\n",
+ " 'expandtabs',\n",
+ " 'find',\n",
+ " 'format',\n",
+ " 'format_map',\n",
+ " 'index',\n",
+ " 'isalnum',\n",
+ " 'isalpha',\n",
+ " 'isdecimal',\n",
+ " 'isdigit',\n",
+ " 'isidentifier',\n",
+ " 'islower',\n",
+ " 'isnumeric',\n",
+ " 'isprintable',\n",
+ " 'isspace',\n",
+ " 'istitle',\n",
+ " 'isupper',\n",
+ " 'join',\n",
+ " 'ljust',\n",
+ " 'lower',\n",
+ " 'lstrip',\n",
+ " 'maketrans',\n",
+ " 'partition',\n",
+ " 'replace',\n",
+ " 'rfind',\n",
+ " 'rindex',\n",
+ " 'rjust',\n",
+ " 'rpartition',\n",
+ " 'rsplit',\n",
+ " 'rstrip',\n",
+ " 'split',\n",
+ " 'splitlines',\n",
+ " 'startswith',\n",
+ " 'strip',\n",
+ " 'swapcase',\n",
+ " 'title',\n",
+ " 'translate',\n",
+ " 'upper',\n",
+ " 'zfill']"
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dir('ABC')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3\n",
+ "3\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('ABC'.__len__())\n",
+ "print(len('ABC'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n",
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def print_weight(self):\n",
+ " print(\"%s : %s\" % (self.name,self.weight))\n",
+ " def run(self):\n",
+ " print('Animal is running')\n",
+ "\n",
+ "dog = Animal('hasky',20)\n",
+ "print(hasattr(dog,'name')) # True\n",
+ "setattr(dog,'height',20)\n",
+ "print(getattr(dog,'height')) # 20"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "dog\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(getattr(dog,'type','dog')) #dog"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ ">\n",
+ "Animal is running\n"
+ ]
+ }
+ ],
+ "source": [
+ "f = getattr(dog,'run')\n",
+ "print(f) # >\n",
+ "f() # Animal is running"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ "dog = Animal('hasky',90)\n",
+ "dog.height = 20 \n",
+ "print(dog.height) # 20"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "ss\n",
+ "ss\n",
+ "aa\n",
+ "ss\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " tt = 'ss'\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ "print(Animal.tt) # ss\n",
+ "dog = Animal('hasky',90) \n",
+ "print(dog.tt) # ss\n",
+ "dog.tt = 'aa'\n",
+ "print(dog.tt) # aa\n",
+ "print(Animal.tt)# ss"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " pass\n",
+ "\n",
+ "ani = Animal()\n",
+ "ani.name = 'hasky'\n",
+ "\n",
+ "from types import MethodType\n",
+ "def set_age(self,age):\n",
+ " self.age = age\n",
+ "\n",
+ "ani.set_age = MethodType(set_age,ani)\n",
+ "ani.set_age(20)\n",
+ "print(ani.age) #20 "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'Animal' object has no attribute 'set_age'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mani2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;31m#print(ani2.name) # AttributeError: 'Animal' object has no attribute 'name'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mani2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_age\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m20\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m: 'Animal' object has no attribute 'set_age'"
+ ]
+ }
+ ],
+ "source": [
+ "ani2 = Animal()\n",
+ "print(ani2.name) # AttributeError: 'Animal' object has no attribute 'name'\n",
+ "ani2.set_age(20) # AttributeError: 'Animal' object has no attribute 'set_age'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "Animal.set_age = set_age\n",
+ "ani2.set_age(20)\n",
+ "print(ani2.age) # 20"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'Animal' object has no attribute 'height'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'hasky'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m90\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mheight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m20\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m: 'Animal' object has no attribute 'height'"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " __slots__ = ['name','weight']\n",
+ " \n",
+ "ani = Animal()\n",
+ "ani.name = 'hasky'\n",
+ "ani.weight = 90\n",
+ "ani.height = 20 # AttributeError: 'Animal' object has no attribute 'height'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Dog(Animal):\n",
+ " pass\n",
+ "dog = Dog()\n",
+ "dog.height = 20\n",
+ "print(dog.height) # 20"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "60\n"
+ ]
+ },
+ {
+ "ename": "ValueError",
+ "evalue": "weight must between 1 ~ 200!",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m60\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m999\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36mset_weight\u001b[0;34m(self, value)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'weight must be an integer!'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m1\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m200\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'weight must between 1 ~ 200!'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0mani\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mValueError\u001b[0m: weight must between 1 ~ 200!"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal(object):\n",
+ "\n",
+ " def get_weight(self):\n",
+ " return self.weight\n",
+ "\n",
+ " def set_weight(self, value):\n",
+ " if not isinstance(value, int):\n",
+ " raise ValueError('weight must be an integer!')\n",
+ " if value < 1 or value > 200:\n",
+ " raise ValueError('weight must between 1 ~ 200!')\n",
+ " self.weight = value\n",
+ "ani = Animal()\n",
+ "ani.set_weight(60)\n",
+ "print(ani.get_weight()) # 60\n",
+ "ani.set_weight(999) # ValueError: weight must between 1 ~ 200!\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "60\n"
+ ]
+ },
+ {
+ "ename": "ValueError",
+ "evalue": "weight must between 1 ~ 200!",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m60\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m \u001b[0mani\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m999\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36mweight\u001b[0;34m(self, value)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'weight must be an integer!'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m1\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m200\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'weight must between 1 ~ 200!'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_weight\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mValueError\u001b[0m: weight must between 1 ~ 200!"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal(object):\n",
+ " @property\n",
+ " def weight(self):\n",
+ " return self._weight\n",
+ " \n",
+ " @weight.setter\n",
+ " def weight(self, value):\n",
+ " if not isinstance(value, int):\n",
+ " raise ValueError('weight must be an integer!')\n",
+ " if value < 1 or value > 200:\n",
+ " raise ValueError('weight must between 1 ~ 200!')\n",
+ " self._weight = value\n",
+ " \n",
+ "ani = Animal()\n",
+ "ani.weight = 60\n",
+ "print(ani.weight) # 60\n",
+ "ani.weight = 999 # ValueError: weight must between 1 ~ 200!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 63,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "60\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal(object):\n",
+ " @property\n",
+ " def birth(self):\n",
+ " return self._birth\n",
+ " \n",
+ " @birth.setter\n",
+ " def birth(self, value):\n",
+ " if not isinstance(value, int):\n",
+ " raise ValueError('birth must be an integer!')\n",
+ " if value < 1 or value > 2018:\n",
+ " raise ValueError('birth must between 1 ~ 2018!')\n",
+ " self._birth = value\n",
+ " \n",
+ " @property\n",
+ " def age(self):\n",
+ " return 2018 - self._birth\n",
+ " \n",
+ "ani = Animal()\n",
+ "ani.birth = 1958\n",
+ "print(ani.age) # 60"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 64,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<__main__.Animal object at 0x104fccd68>\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(ani) # <__main__.Animal object at 0x104fccd68>"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 68,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Animal object with name : tt\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "<__main__.Animal at 0x104e8ecf8>"
+ ]
+ },
+ "execution_count": 68,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "class Animal(object):\n",
+ " def __init__(self,name):\n",
+ " self.name = name\n",
+ " def __str__(self):\n",
+ " return 'Animal object with name : %s' % self.name\n",
+ "print(Animal('tt')) # Animal object with name : tt\n",
+ "a = Animal('tt')\n",
+ "a # <__main__.Animal at 0x104e8ecf8>"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 71,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1\n",
+ "1\n",
+ "2\n",
+ "3\n",
+ "5\n",
+ "8\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Fib(object):\n",
+ " def __init__(self):\n",
+ " self.a, self.b = 0, 1 # 初始化两个计数器a,b\n",
+ "\n",
+ " def __iter__(self):\n",
+ " return self # 实例本身就是迭代对象,故返回自己\n",
+ "\n",
+ " def __next__(self):\n",
+ " self.a, self.b = self.b, self.a + self.b # 计算下一个值\n",
+ " if self.a > 10: # 退出循环的条件\n",
+ " raise StopIteration()\n",
+ " return self.a # 返回下一个值\n",
+ "for n in Fib():\n",
+ " print(n)\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 73,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[2, 3, 5]\n",
+ "89\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Fib(object):\n",
+ " def __getitem__(self, n):\n",
+ " if isinstance(n, int): # n是索引\n",
+ " a, b = 1, 1\n",
+ " for x in range(n):\n",
+ " a, b = b, a + b\n",
+ " return a\n",
+ " if isinstance(n, slice): # n是切片\n",
+ " start = n.start\n",
+ " stop = n.stop\n",
+ " if start is None:\n",
+ " start = 0\n",
+ " a, b = 1, 1\n",
+ " L = []\n",
+ " for x in range(stop):\n",
+ " if x >= start:\n",
+ " L.append(a)\n",
+ " a, b = b, a + b\n",
+ " return L\n",
+ "f = Fib()\n",
+ "print(f[2:5]) # [1, 1, 2, 3, 5]\n",
+ "print(f[10]) # 89"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 74,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def __getattr__(self,attr):\n",
+ " if attr == 'height':\n",
+ " return 20\n",
+ "a = Animal(\"hasky\",90)\n",
+ "print(a.height) # 20"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "20\n",
+ "25\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def __getattr__(self,attr):\n",
+ " if attr == 'height':\n",
+ " return 20\n",
+ " elif attr == 'age':\n",
+ " return lambda: 25\n",
+ "a = Animal(\"hasky\",90)\n",
+ "print(a.height) # 20\n",
+ "print(a.age()) # 25"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 78,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "Animal object has no attribute abc",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Animal object has no attribute %s'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mattr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"hasky\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m90\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mabc\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, attr)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mattr\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'age'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;32mlambda\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m25\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Animal object has no attribute %s'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mattr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"hasky\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m90\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mabc\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mAttributeError\u001b[0m: Animal object has no attribute abc"
+ ]
+ }
+ ],
+ "source": [
+ "class Animal():\n",
+ " def __init__(self,name,weight):\n",
+ " self.name = name\n",
+ " self.weight = weight\n",
+ " def __getattr__(self,attr):\n",
+ " if attr == 'height':\n",
+ " return 20\n",
+ " elif attr == 'age':\n",
+ " return lambda: 25\n",
+ " raise AttributeError('Animal object has no attribute %s' % attr)\n",
+ "a = Animal(\"hasky\",90)\n",
+ "print(a.abc) # AttributeError: Animal object has no attribute abc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}