一个案例深入Python中的__new__和__init__

准备

在Python中,一切皆对象。

既然一切皆对象,那么类也是对象,我们暂且称之为 类对象。来个简单例子(本篇文章的所有案例都是运行在Python3.4中):

class foo():
    pass

print(id(foo))     
print(type(foo))

# 结果:
# 46627056
# <class 'type'>

如果想深入了解一下,可以看:深刻理解Python中的元类(metaclass)

 

引入

最近在阅读tornado源码,发现在其源码中有很多类是这样的:

class HTTPServer(TCPServer, Configurable,
                 httputil.HTTPServerConnectionDelegate):

    def __init__(self, *args, **kwargs):
        # Ignore args to __init__; real initialization belongs in
        # initialize since we're Configurable. 就是说默认的__init__初始化方法不在起作用了,改为了initialize方法进行初始化
        pass

或者是干脆没有__init__ ,只写了个initialize方法来替代。

所以心生疑惑,tornado是如何做到这一点的?

 

正题

接下来我们来了解一下,Python解释器是如何创建对象的。

大家可能对Python中的__init__方法很熟悉,认为他是实例化类时调用的第一个方法。但其实他并不是。实例化时调用的第一个方法其实是__new__方法。

 

好了,接下来是重点:

  1  当我们实例化A类对象时,Python中首先调用的是该A类对象的__new__方法,如果该A类对象没有定义__new__方法,则去父类中依次查找,直到object类

  2  object类有一个__new__方法,该方法接收一个参数(一般为类对象),将该参数进行实例化并返回一个对象

  3  Python解释器会将调用__new__方法并将A类对象作为第一个参数传入,最后会返回一个对象(这个对象就是A类的实例对象,我们称之为a1)

  4  Python解释器默认会调用a1对象的__init__方法,并将参数传入。

来一个例子验证一下:

class asd(object):
    def __new__(cls, *args, **kwargs):
        print('asd.__new__() is running. cls id is %s'%id(cls))
        r = super(asd,cls).__new__(cls)
        print('r_id is %s'%id(r))
        return r


class bnm(asd):

    def __init__(self,name):
        print('bnm.__init__() is running, self id is %s'%id(self))
        self.name = name
        print('bnm.name is %s'%(self.name))

print('asd_id is %s'%id(asd))
print('bnm_id is %s'%id(bnm))
o1 = bnm('ni')
print('o1_id is',id(o1))

# asd_id is 49838320
# bnm_id is 49838768
# asd.__new__() is running. cls id is 49838768
# r_id is 49848400
# bnm.__init__() is running, self id is 49848400
# bnm.name is ni
# o1_id is 49848400
注意 : bnm 和 cls 是同一个对象! r 和 o1 也是同一个对象 !

 

应用

仿tornado实现自定义类的初始化方法:

class asd(object):
    def __new__(cls, *args, **kwargs):
        r = super(asd,cls).__new__(cls)
        r.initialize(*args)
        return r

class bnm(asd):

    def initialize(self):
        print('bnm_initialize is running')

class foo(asd):

    def initialize(self,name):
        self.name = name
        print('foo_initialize is running, my name is %s' %(self.name))


r = bnm()
r1 = foo('linghuchong')

# bnm_initialize is running
# foo_initialize is running, my name is linghuchong
View Code

 

定义类时,只要继承了asd类,就会将initialize方法作为初始化方法,是不是感觉很(wu)酷(lun)炫(yong)?

 

转载于:https://www.cnblogs.com/MnCu8261/p/6365665.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个基于TensorFlow 2.0的DDPG(Deep Deterministic Policy Gradient)算法的简单示例: ```python import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import Adam class Actor(tf.keras.Model): def __init__(self, state_dim, action_dim, max_action): super(Actor, self).__init__() self.hidden1 = Dense(256, activation='relu') self.hidden2 = Dense(256, activation='relu') self.output_layer = Dense(action_dim, activation='tanh') self.max_action = max_action def call(self, inputs): x = self.hidden1(inputs) x = self.hidden2(x) x = self.output_layer(x) return self.max_action * x class Critic(tf.keras.Model): def __init__(self, state_dim, action_dim): super(Critic, self).__init__() self.hidden1 = Dense(256, activation='relu') self.hidden2 = Dense(256, activation='relu') self.output_layer = Dense(1) def call(self, state, action): x = tf.concat([state, action], axis=1) x = self.hidden1(x) x = self.hidden2(x) return self.output_layer(x) class DDPG: def __init__(self, state_dim, action_dim, max_action): self.actor = Actor(state_dim, action_dim, max_action) self.critic = Critic(state_dim, action_dim) self.target_actor = Actor(state_dim, action_dim, max_action) self.target_critic = Critic(state_dim, action_dim) self.actor_optimizer = Adam(learning_rate=0.001) self.critic_optimizer = Adam(learning_rate=0.001) self.tau = 0.005 def get_action(self, state): state = tf.expand_dims(tf.convert_to_tensor(state), 0) action = self.actor(state)[0] return action.numpy() def train(self, replay_buffer, batch_size=64, gamma=0.99): states, actions, next_states, rewards, dones = replay_buffer.sample_batch(batch_size) with tf.GradientTape() as tape: target_actions = self.target_actor(next_states) target_q_values = self.target_critic(next_states, target_actions) target_q_values = rewards + gamma * target_q_values * (1 - dones) q_values = self.critic(states, actions) critic_loss = tf.reduce_mean(tf.square(q_values - target_q_values)) critic_grad = tape.gradient(critic_loss, self.critic.trainable_variables) self.critic_optimizer.apply_gradients(zip(critic_grad, self.critic.trainable_variables)) with tf.GradientTape() as tape: new_actions = self.actor(states) actor_loss = -tf.reduce_mean(self.critic(states, new_actions)) actor_grad = tape.gradient(actor_loss, self.actor.trainable_variables) self.actor_optimizer.apply_gradients(zip(actor_grad, self.actor.trainable_variables)) self.update_target_networks() def update_target_networks(self): for target, source in zip(self.target_actor.trainable_variables, self.actor.trainable_variables): target.assign(self.tau * source + (1 - self.tau) * target) for target, source in zip(self.target_critic.trainable_variables, self.critic.trainable_variables): target.assign(self.tau * source + (1 - self.tau) * target) # 示例用法 state_dim = 4 action_dim = 2 max_action = 1 ddpg = DDPG(state_dim, action_dim, max_action) # 训练循环 for episode in range(num_episodes): # 执行动作并观察环境 action = ddpg.get_action(state) next_state, reward, done, _ = env.step(action) # 将经验存储到回放缓冲区 replay_buffer.add(state, action, next_state, reward, done) # 更新DDPG算法 ddpg.train(replay_buffer) # 更新当前状态 state = next_state ``` 这只是一个简单的DDPG算法示例,实际应用可能需要进行更多的调优和改进。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值