在ReactiveX中,如何将其他参数传递给Observer.create?

时间:2017-10-22 16:30:51

标签: python reactivex rx-py

使用RxPY进行说明。

我想从函数创建一个observable,但该函数必须带参数。这个特定的例子必须以随机的间隔返回我想发送给它的许多预定义的代码之一。到目前为止,我的解决方案是使用闭包:

from __future__ import print_function

from rx import Observable
import random
import string
import time

def make_tickers(n = 300, s = 123):
    """ generates up to n unique 3-letter strings geach makde up of uppsercase letters"""
    random.seed(s)
    tickers = [''.join(random.choice(string.ascii_uppercase) for _ in range(3)) for y in range(n)]
    tickers = list(set(tickers)) # unique
    print(len(tickers))
    return(tickers)

def spawn_prices_fn(tickers):
    """ returns a function that will return a random element 
    out of tickers every 20-100 ms, and takes an observable parameter """

    def spawner(observer):
        while True:
            next_tick = random.choice(tickers)
            observer.on_next(next_tick)
            time.sleep(random.randint(20, 100)/1000.0)

    return(spawner)


if __name__ == "__main__":
    spawned = spawn_prices_fn(make_tickers())
    xx = Observable.create(spawned)
    xx.subscribe(lambda s: print(s))

有更简单的方法吗?可以将其他参数发送到Observable.create的第一个参数函数,它不需要闭包吗?什么是规范建议?

2 个答案:

答案 0 :(得分:1)

它可以通过多种方式完成,这里的解决方案之一并没有太多改变您的代码。 请注意,代码生成也可以分解为一个函数,生成一个字符串,结合一些<?php /* Woocommerce plugin details */ if (!defined('ABSPATH')) { exit; // Exit if accessed directly } /** * Check if WooCommerce is active **/ if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) { function my_shipping_method() { if (!class_exists('my_shipping_method')) { class my_shipping_method extends WC_Shipping_Method { /** * Constructor for the shipping class * * @access public * @return void */ public function __construct() { $this->id = 'my_shipping_method'; $this->method_title = __('Custom Ondemand Shipping', 'my_shipping_method'); $this->method_description = __('Custom Shipping Method for Custom Ondemand', 'my_shipping_method'); // Availability & Countries $this->availability = 'including'; $this->countries = array('KE'); $this->init(); $this->enabled = isset($this->settings['enabled']) ? $this->settings['enabled'] : 'yes'; $this->title = isset($this->settings['title']) ? $this->settings['title'] : __('Custom Ondemand Shipping', 'my_shipping_method'); $this->API_username = isset($this->settings['API_username']) ? $this->settings['API_username'] : 'myusername'; $this->API_key = isset($this->settings['API_key']) ? $this->settings['API_key'] : 'mykey'; $this->CUSTOM_LIVE_URL = 'https://api.custom.com/v1'; $this->CUSTOM_TEST_URL = 'https://apitest.custom.com/v1/'; $this->CUSTOM_URL = (isset($this->settingd['USE_LIVE_API']) && $this->settingd['USE_LIVE_API'] == 'yes' )? $this->CUSTOM_LIVE_URL : $this->CUSTOM_TEST_URL; } /** * Init the settings * * @access public * @return void */ function init() { // Load the settings API $this->init_form_fields(); $this->init_settings(); // Save settings in admin if you have any defined add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options')); //register google maps places library wp_register_script('mapsPlaces', 'https://maps.googleapis.com/maps/api/js?key=' . $this->settings['maps_API_key'] . '&libraries=places', array(), false); wp_register_style('main_style', plugins_url('css/my_shipping_method-woocommerce.css', __FILE__)); wp_enqueue_style('main_style'); } /** * Define settings field for this shipping * @return void */ function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __('Enable', 'my_shipping_method'), 'type' => 'checkbox', 'description' => __('Enable this shipping method.', 'my_shipping_method'), 'default' => 'yes' ), 'USE_LIVE_API' => array( 'title' => __('Use Live API', 'my_shipping_method'), 'type' => 'checkbox', 'description' => __('Check if you want to use the live API or uncheck to use the test API.', 'my_shipping_method'), 'default' => 'yes' ), 'title' => array( 'title' => __('Title', 'my_shipping_method'), 'type' => 'text', 'description' => __('Title displayed to users', 'my_shipping_method'), 'default' => __('Custom Ondemand', 'my_shipping_method') ), 'API_username' => array( 'title' => __('Custom Ondemand username', 'my_shipping_method'), 'type' => 'text', 'description' => __('Custom Ondemand merchant username. You can signup here <a href="http://custom.com">http://custom.com</a>', 'my_shipping_method'), 'default' => __('myusername', 'my_shipping_method') ), 'API_key' => array( 'title' => __('Custom Ondemand API key', 'my_shipping_method'), 'type' => 'text', 'description' => __('Custom Ondemand merchant API key. You can find it in your Custom Ondemand merchant profile', 'my_shipping_method'), 'default' => __('mykey', 'my_shipping_method') ), 'maps_API_key' => array( 'title' => __('Maps API key', 'my_shipping_method'), 'type' => 'text', 'description' => __('Google maps API key. You can find it Go to the <a href="https://console.developers.google.com/project/_/apiui/apis/enabled">Google API Console</a>' . 'Click the Select a project button, then select the same project you set up for the Google Maps JavaScript API and click Open.' . 'From the list of APIs on the Dashboard, look for Google Places API Web Service.' . 'If you see the API in the list, you are all set. If the API is not listed, enable it:' . 'At the top of the page, select ENABLE API to display the Library tab. Alternatively, from the left side menu, select Library.' . 'Search for Google Places API Web Service, then select it from the results list.' . 'Select ENABLE. When the process finishes, Google Places API Web Service appears in the list of APIs on the Dashboard.' , 'my_shipping_method'), 'default' => __('mapskey', 'my_shipping_method') ), ); } /** * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters. * * @access public * @param mixed $package * @return void */ public function calculate_shipping($package = Array()) { $cost = 150; $weight = 0; parse_str($_POST['post_data'], $order_data); $to_name = ""; $to_lat = ""; $to_long = ""; $recepient_name = ""; $recepient_phone = ""; $recepient_email = ""; if ($order_data['ship_to_different_address']) { $to_name = $order_data['shipping_address_1']; $to_lat = $order_data['shipping_lat']; $to_long = $order_data['shipping_lng']; $recepient_name = $order_data['shipping_first_name'] . " " . $order_data['shipping_last_name']; $recepient_phone = isset($order_data['shipping_phone']) ? $order_data['shipping_phone'] : $order_data['billing_phone']; $recepient_email = isset($order_data['shipping_email']) ? $order_data['shipping_email'] : $order_data['billing_email']; } else { $to_name = $order_data['billing_address_1']; $to_lat = $order_data['billing_lat']; $to_long = $order_data['billing_lng']; $recepient_name = $order_data['billing_first_name'] . " " . $order_data['billing_last_name']; $recepient_phone = $order_data['billing_phone']; $recepient_email = $order_data['billing_email']; } foreach ($package['contents'] as $item_id => $values) { $_product = $values['data']; if ($_product->has_weight()) { $weight = $weight + $_product->weight() * $values['quantity']; } } $api_username = $this->settings['API_username']; $api_key = $this->settings['API_key']; $data = '';//data passed to the api. Tested to be okay. $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL =>$this->CUSTOM_URL, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $data, CURLOPT_HTTPHEADER => array( "cache-control: no-cache", "content-type: application/json" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { $cost = 200; } else { // echo $response; $result = json_decode($response, true); $cost = $result['data']['amount']; } $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $cost ); $this->add_rate($rate); } } } } add_action('woocommerce_shipping_init', 'my_shipping_method'); function add_my_shipping_method($methods) { $methods['my_shipping_method'] = 'my_shipping_method'; return $methods; } add_filter('woocommerce_shipping_methods', 'add_my_shipping_method'); function my_shipping_method_validate_order($posted) { $packages = WC()->shipping->get_packages(); $chosen_methods = WC()->session->get('chosen_shipping_methods'); if (is_array($chosen_methods) && in_array('my_shipping_method', $chosen_methods)) { foreach ($packages as $i => $package) { if ($chosen_methods[$i] != "my_shipping_method") { continue; } $my_shipping_method = new my_shipping_method(); $weight = 0; foreach ($package['contents'] as $item_id => $values) { $_product = $values['data']; if ($_product->has_weight()) { $weight = $weight + $_product->weight * $values['quantity']; } } $weight = wc_get_weight($weight, 'kg'); } } } // add_action('woocommerce_review_order_before_cart_contents', 'my_shipping_method_validate_order', 10); // add_action('woocommerce_after_checkout_validation', 'my_shipping_method_validate_order', 10); // Hook in add_filter('woocommerce_checkout_fields', 'my_shipping_method_override_checkout_fields'); // Our hooked in function - $fields is passed via the filter! function my_shipping_method_override_checkout_fields($fields) { // load the autocomplete script wp_enqueue_script('my_shipping_method-woocommerce', plugin_dir_url(__FILE__) . 'js/my_shipping_method-woocommerce.js', array('mapsPlaces')); $fields['shipping']['shipping_lat'] = array( 'label' => __('Latitude', 'my_shipping_method'), 'placeholder' => _x('Lat', 'placeholder', 'my_shipping_method'), 'required' => true, 'class' => array('form-row-first', 'placesAutoComplete', 'hidden'), 'label_class' => array('hidden'), 'clear' => true ); $fields['shipping']['shipping_lng'] = array( 'label' => __('Longitude', 'my_shipping_method'), 'placeholder' => _x('long', 'placeholder', 'my_shipping_method'), 'required' => true, 'class' => array('form-row-last', 'placesAutoComplete', 'hidden'), 'label_class' => array('hidden'), 'clear' => true ); $fields['billing']['billing_lat'] = array( 'label' => __('Latitude', 'my_shipping_method'), 'placeholder' => _x('Lat', 'placeholder', 'my_shipping_method'), 'required' => true, 'class' => array('form-row-first', 'placesAutoComplete', 'hidden'), 'label_class' => array('hidden'), 'clear' => true ); $fields['billing']['billing_lng'] = array( 'label' => __('Longitude', 'my_shipping_method'), 'placeholder' => _x('long', 'placeholder', 'my_shipping_method'), 'required' => true, 'class' => array('form-row-last', 'placesAutoComplete', 'hidden'), 'label_class' => array('hidden'), 'clear' => true ); return $fields; } /** * Display field value on the order edit page */ add_action('woocommerce_admin_order_data_after_shipping_address', 'my_shipping_method_custom_checkout_field_display_admin_order_meta', 10, 1); function my_shipping_method_custom_checkout_field_display_admin_order_meta($order) { echo '<p><strong>' . __('Delivery location') . ':</strong> ' . get_post_meta($order->get_id(), '_shipping_location', true) . '</p>'; } /** * Process the checkout */ add_action('woocommerce_checkout_process', 'location_checkout_field_process'); function location_checkout_field_process() { // // Check if set, if its not set add an error. // if (!$_POST['shipping_location'] && !$_POST['billing_location']) // wc_add_notice(__('Please enter a biling location.'), 'error'); // // } // FORCE SHIPPING COST RECALCULATION WC()->cart->calculate_shipping(); WC()->cart->calculate_totals(); } } 魔法更多 array.reverse() - 就像

我还稍微调整了代码以使rx满意

rx

或没有flake8的解决方案:

from __future__ import print_function

import random
import string
import time

from rx import Observable


def make_tickers(n=300, s=123):
    """
    Generates up to n unique 3-letter strings each made up of uppercase letters
    """
    random.seed(s)
    tickers = [''.join(random.choice(string.ascii_uppercase) for _ in range(3))
               for y in range(n)]
    tickers = list(set(tickers))  # unique
    print(len(tickers))
    return(tickers)


def random_picker(tickers):
    ticker = random.choice(tickers)
    time.sleep(random.randint(20, 100) / 1000.0)
    return ticker


if __name__ == "__main__":
    xx = Observable\
        .repeat(make_tickers())\
        .map(random_picker)\
        .subscribe(lambda s: print(s))

make_tickers可以从from __future__ import print_function import random import string import time from rx import Observable def random_picker(tickers): ticker = random.choice(tickers) time.sleep(random.randint(20, 100) / 1000.0) return ticker if __name__ == "__main__": random.seed(123) Observable.range(1, 300)\ .map(lambda _: ''.join(random.choice(string.ascii_uppercase) for _ in range(3)))\ .reduce(lambda x, y: x + [y], [])\ .do_while(lambda _: True)\ .map(random_picker)\ .subscribe(lambda s: print(s)) 移开,但代码会变得有点棘手

答案 1 :(得分:0)

您还可以使用“partials”来包装您的订阅方法。它允许您定义其他参数,但在仅等待 Observer 和 Scheduler 的方法上调用 rx.create:

res.status(400).json({ message: `There is user with email ${email}` });
return;