javascript

git

java

python

git-remote

c++

github

django

c#

reactjs

node.js

performance

branch-prediction

git-commit

git-revert

validation

email-validation

undefined

scrum

kubernetes

生成器线程安全吗?

我有一个多线程程序,在其中创建生成器函数,然后将其传递给新线程。 我希望它本质上是共享的/全局的,以便每个线程都可以从生成器获取下一个值。

使用这样的生成器是否安全,还是会遇到从多个线程访问共享生成器的问题/情况?

如果不是,是否有更好的方法来解决该问题? 我需要可以遍历列表并为任何线程调用它生成下一个值的东西。

trans by 2020-08-09T21:59:43Z

如何使用Python C API创建生成器/迭代器?

如何使用Python C API复制以下Python代码?

class Sequence():
    def __init__(self, max):
        self.max = max
    def data(self):
        i = 0
        while i < self.max:
            yield i
            i += 1

到目前为止,我有这个:

#include <Python/Python.h>
#include <Python/structmember.h>

/* Define a new object class, Sequence. */
typedef struct {
    PyObject_HEAD
    size_t max;
} SequenceObject;

/* Instance variables */
static PyMemberDef Sequence_members[] = {
    {"max", T_UINT, offsetof(SequenceObject, max), 0, NULL},
    {NULL} /* Sentinel */
};

static int Sequence_Init(SequenceObject *self, PyObject *args, PyObject *kwds)
{
    if (!PyArg_ParseTuple(args, "k", &(self->max))) {
        return -1;
    }
    return 0;
}

static PyObject *Sequence_data(SequenceObject *self, PyObject *args);

/* Methods */
static PyMethodDef Sequence_methods[] = {
    {"data", (PyCFunction)Sequence_data, METH_NOARGS,
     "sequence.data() -> iterator object\n"
     "Returns iterator of range [0, sequence.max)."},
    {NULL} /* Sentinel */
};

/* Define new object type */
PyTypeObject Sequence_Type = {
   PyObject_HEAD_INIT(NULL)
   0,                         /* ob_size */
   "Sequence",                /* tp_name */
   sizeof(SequenceObject),    /* tp_basicsize */
   0,                         /* tp_itemsize */
   0,                         /* tp_dealloc */
   0,                         /* tp_print */
   0,                         /* tp_getattr */
   0,                         /* tp_setattr */
   0,                         /* tp_compare */
   0,                         /* tp_repr */
   0,                         /* tp_as_number */
   0,                         /* tp_as_sequence */
   0,                         /* tp_as_mapping */
   0,                         /* tp_hash */
   0,                         /* tp_call */
   0,                         /* tp_str */
   0,                         /* tp_getattro */
   0,                         /* tp_setattro */
   0,                         /* tp_as_buffer */
   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
   "Test generator object",   /* tp_doc */
   0,                         /* tp_traverse */
   0,                         /* tp_clear */
   0,                         /* tp_richcompare */
   0,                         /* tp_weaklistoffset */
   0,                         /* tp_iter */
   0,                         /* tp_iternext */
   0,                         /* tp_methods */
   Sequence_members,          /* tp_members */
   0,                         /* tp_getset */
   0,                         /* tp_base */
   0,                         /* tp_dict */
   0,                         /* tp_descr_get */
   0,                         /* tp_descr_set */
   0,                         /* tp_dictoffset */
   (initproc)Sequence_init,   /* tp_init */
   0,                         /* tp_alloc */
   PyType_GenericNew,         /* tp_new */
};

static PyObject *Sequence_data(SequenceObject *self, PyObject *args)
{
    /* Now what? */
}

但我不确定下一步要去哪里。 有人可以提供一些建议吗?

编辑

我想我遇到的主要问题是模拟StopIteration语句。 据我了解,这是一个看起来很简单但实际上很复杂的语句-它使用自己的2994411917034390590529和2994411917034390590530方法创建了一个生成器,这些方法会自动调用。 搜索文档,它似乎与PyGenObject相关联; 但是,如何创建该对象的新实例尚不清楚。 PyGen_New()PyFrameObject作为其参数,我可以找到的唯一参考是StopIteration,这似乎不是我想要的(或者我弄错了吗?)。 有谁可以分享这些经验吗?

进一步编辑

当我(基本上)扩展Python在幕后所做的工作时,我发现这一点更加清楚:

class IterObject():
    def __init__(self, max):
        self.max = max
    def __iter__(self):
        self.i = 0
        return self
    def next(self):
        if self.i >= self.max:
            raise StopIteration
        self.i += 1
        return self.i

class Sequence():
    def __init__(self, max):
        self.max = max
    def data(self):
        return IterObject(self.max)

从技术上讲,顺序是一一完成的,但是您可以理解。

唯一的问题是,每当需要一个生成器时创建一个新对象就很烦人。由于定义新类型会带来怪异,因此在Python中使用C生成的对象比使用C生成的对象还要多。 由于C没有闭包,因此C中不能有StopIteration语句。 相反,我所做的是(因为我无法在Python API中找到它-如果已经存在,请指向一个标准对象!)是创建一个简单的通用生成器对象类,该类针对每个next()方法调用都调用一个C函数 。 在这里(请注意,我尚未尝试编译它,因为它不完整-见下文):

#include <Python/Python.h>
#include <Python/structmember.h>
#include <stdlib.h>

/* A convenient, generic generator object. */

typedef PyObject *(*callback)(PyObject *callee, void *info) PyGeneratorCallback;

typedef struct {
    PyObject HEAD
    PyGeneratorCallback callback;
    PyObject *callee;
    void *callbackInfo; /* info to be passed along to callback function. */
    bool freeInfo; /* true if |callbackInfo| should be free'()d when object
                    * dealloc's, false if not. */
} GeneratorObject;

static PyObject *Generator_iter(PyObject *self, PyObject *args)
{
    Py_INCREF(self);
    return self;
}

static PyObject *Generator_next(PyObject *self, PyObject *args)
{
    return self->callback(self->callee, self->callbackInfo);
}

static PyMethodDef Generator_methods[] = {
    {"__iter__", (PyCFunction)Generator_iter, METH_NOARGS, NULL},
    {"next", (PyCFunction)Generator_next, METH_NOARGS, NULL},
    {NULL} /* Sentinel */
};

static void Generator_dealloc(GenericEventObject *self)
{
    if (self->freeInfo && self->callbackInfo != NULL) {
        free(self->callbackInfo);
    }
    self->ob_type->tp_free((PyObject *)self);
}

PyTypeObject Generator_Type = {
   PyObject_HEAD_INIT(NULL)
   0,                         /* ob_size */
   "Generator",               /* tp_name */
   sizeof(GeneratorObject),   /* tp_basicsize */
   0,                         /* tp_itemsize */
   Generator_dealloc,         /* tp_dealloc */
   0,                         /* tp_print */
   0,                         /* tp_getattr */
   0,                         /* tp_setattr */
   0,                         /* tp_compare */
   0,                         /* tp_repr */
   0,                         /* tp_as_number */
   0,                         /* tp_as_sequence */
   0,                         /* tp_as_mapping */
   0,                         /* tp_hash */
   0,                         /* tp_call */
   0,                         /* tp_str */
   0,                         /* tp_getattro */
   0,                         /* tp_setattro */
   0,                         /* tp_as_buffer */
   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
   0,                         /* tp_doc */
   0,                         /* tp_traverse */
   0,                         /* tp_clear */
   0,                         /* tp_richcompare */
   0,                         /* tp_weaklistoffset */
   0,                         /* tp_iter */
   0,                         /* tp_iternext */
   0,                         /* tp_methods */
   0,                         /* tp_members */
   0,                         /* tp_getset */
   0,                         /* tp_base */
   0,                         /* tp_dict */
   0,                         /* tp_descr_get */
   0,                         /* tp_descr_set */
   0,                         /* tp_dictoffset */
   0,                         /* tp_init */
   0,                         /* tp_alloc */
   PyType_GenericNew,         /* tp_new */
};

/* Returns a new generator object with the given callback function
 * and arguments. */
PyObject *Generator_New(PyObject *callee, void *info,
                        bool freeInfo, PyGeneratorCallback callback)
{
    GeneratorObject *generator = (GeneratorObject *)_PyObject_New(&Generator_Type);
    if (generator == NULL) return NULL;

    generator->callee = callee;
    generator->info = info;
    generator->callback = callback;
    self->freeInfo = freeInfo;

    return (PyObject *)generator;
}

/* End of Generator definition. */

/* Define a new object class, Sequence. */
typedef struct {
    PyObject_HEAD
    size_t max;
} SequenceObject;

/* Instance variables */
static PyMemberDef Sequence_members[] = {
    {"max", T_UINT, offsetof(SequenceObject, max), 0, NULL},
    {NULL} /* Sentinel */
}

static int Sequence_Init(SequenceObject *self, PyObject *args, PyObject *kwds)
{
    if (!PyArg_ParseTuple(args, "k", &self->max)) {
        return -1;
    }
    return 0;
}

static PyObject *Sequence_data(SequenceObject *self, PyObject *args);

/* Methods */
static PyMethodDef Sequence_methods[] = {
    {"data", (PyCFunction)Sequence_data, METH_NOARGS,
     "sequence.data() -> iterator object\n"
     "Returns generator of range [0, sequence.max)."},
    {NULL} /* Sentinel */
};

/* Define new object type */
PyTypeObject Sequence_Type = {
   PyObject_HEAD_INIT(NULL)
   0,                         /* ob_size */
   "Sequence",                /* tp_name */
   sizeof(SequenceObject),    /* tp_basicsize */
   0,                         /* tp_itemsize */
   0,                         /* tp_dealloc */
   0,                         /* tp_print */
   0,                         /* tp_getattr */
   0,                         /* tp_setattr */
   0,                         /* tp_compare */
   0,                         /* tp_repr */
   0,                         /* tp_as_number */
   0,                         /* tp_as_sequence */
   0,                         /* tp_as_mapping */
   0,                         /* tp_hash */
   0,                         /* tp_call */
   0,                         /* tp_str */
   0,                         /* tp_getattro */
   0,                         /* tp_setattro */
   0,                         /* tp_as_buffer */
   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
   "Test generator object",   /* tp_doc */
   0,                         /* tp_traverse */
   0,                         /* tp_clear */
   0,                         /* tp_richcompare */
   0,                         /* tp_weaklistoffset */
   0,                         /* tp_iter */
   0,                         /* tp_iternext */
   0,                         /* tp_methods */
   Sequence_members,          /* tp_members */
   0,                         /* tp_getset */
   0,                         /* tp_base */
   0,                         /* tp_dict */
   0,                         /* tp_descr_get */
   0,                         /* tp_descr_set */
   0,                         /* tp_dictoffset */
   (initproc)Sequence_init,   /* tp_init */
   0,                         /* tp_alloc */
   PyType_GenericNew,         /* tp_new */
};

static PyObject *Sequence_data(SequenceObject *self, PyObject *args)
{
    size_t *info = malloc(sizeof(size_t));
    if (info == NULL) return NULL;
    *info = 0;

    /* |info| will be free'()d by the returned generator object. */
    GeneratorObject *ret = Generator_New(self, info, true,
                                         &Sequence_data_next_callback);
    if (ret == NULL) {
        free(info); /* Watch out for memory leaks! */
    }
    return ret;
}

PyObject *Sequence_data_next_callback(PyObject *self, void *info)
{
    size_t i = info;
    if (i > self->max) {
        return NULL; /* TODO: How do I raise StopIteration here? I can't seem to find
                      *       a standard exception. */
    } else {
        return Py_BuildValue("k", i++);
    }
}

但是,不幸的是,我还没有完成。 我剩下的唯一问题是:如何使用C API引发StopIteration异常? 我似乎找不到标准例外中列出的内容。 另外,也许更重要的是,这是解决此问题的正确方法吗?

感谢任何仍在遵循此规则的人。

trans by 2020-08-03T01:36:49Z

python-如何以Python方式从列表中产生所有值?

假设我有一个列表,希望不返回而是从中产生值。 最Python的方式是什么?

这就是我的意思。 多亏了一些非延迟计算,我才计算出了列表2989579180238238701568,但是我在整个项目中的代码使用了延迟计算,因此我想从函数中产生值,而不是返回整个列表。

我目前将其编写如下:

my_list = ['a', 'b', 'c', 'd']
for item in my_list:
    yield item

但这对我来说并不好用。

trans by 2020-07-30T17:35:23Z

异常-如何获取Python生成器以返回None而不是StopIteration?

我正在使用生成器在类似于以下简单示例的列表中执行搜索:

>>> a = [1,2,3,4]
>>> (i for i, v in enumerate(a) if v == 4).next()
3

(仅举例说明一下,与上面的列表相比,我使用的列表要长得多,并且条目比None还要复杂一些。我这样做是为了避免每次遍历整个列表 我搜索他们)

现在,如果我改为将其更改为None,它将返回try ... except,因为在a中找不到任何666条目。

如何使它返回None? 我当然可以将其包装在try ... except子句中,但是还有更多的Python方式可以做到这一点吗?

trans by 2020-07-21T06:14:22Z

python-将生成器拆分为多个块,而无需预先遍历

(这个问题与此相关,但是这些问题是在发电机前进行的,这正是我要避免的问题)

我想将生成器拆分为多个块。 要求是:

  • 不要填充数据块:如果剩余元素的数量小于数据块大小,则最后一个数据块必须较小。
  • 不要事先走生成器:计算元素是昂贵的,并且必须仅通过使用函数来完成,而不是通过分块器来完成
  • 这当然意味着:不要在内存中累积(无列表)

我尝试了以下代码:

def head(iterable, max=10):
    for cnt, el in enumerate(iterable):
        yield el
        if cnt >= max:
            break

def chunks(iterable, size=10):
    i = iter(iterable)
    while True:
        yield head(i, size)

# Sample generator: the real data is much more complex, and expensive to compute
els = xrange(7)

for n, chunk in enumerate(chunks(els, 3)):
    for el in chunk:
        print 'Chunk %3d, value %d' % (n, el)

这以某种方式起作用:

Chunk   0, value 0
Chunk   0, value 1
Chunk   0, value 2
Chunk   1, value 3
Chunk   1, value 4
Chunk   1, value 5
Chunk   2, value 6
^CTraceback (most recent call last):
  File "xxxx.py", line 15, in <module>
    for el in chunk:
  File "xxxx.py", line 2, in head
    for cnt, el in enumerate(iterable):
KeyboardInterrupt

Buuuut ...因为2964171943525745745665,它永远不会停止(我必须按chunks)。无论何时使用完发电机,我都想停止该循环,但是我不知道如何检测这种情况。 我试图提出一个异常:

class NoMoreData(Exception):
    pass

def head(iterable, max=10):
    for cnt, el in enumerate(iterable):
        yield el
        if cnt >= max:
            break
    if cnt == 0 : raise NoMoreData()

def chunks(iterable, size=10):
    i = iter(iterable)
    while True:
        try:
            yield head(i, size)
        except NoMoreData:
            break

# Sample generator: the real data is much more complex, and expensive to compute    
els = xrange(7)

for n, chunk in enumerate(chunks(els, 2)):
    for el in chunk:
        print 'Chunk %3d, value %d' % (n, el)

但是然后仅在使用方的上下文中引发异常,这不是我想要的(我想保持使用方代码干净)

Chunk   0, value 0
Chunk   0, value 1
Chunk   0, value 2
Chunk   1, value 3
Chunk   1, value 4
Chunk   1, value 5
Chunk   2, value 6
Traceback (most recent call last):
  File "xxxx.py", line 22, in <module>
    for el in chunk:
  File "xxxx.py", line 9, in head
    if cnt == 0 : raise NoMoreData
__main__.NoMoreData()

如何在chunks功能中检测到发电机已耗尽,而没有行走?

trans by 2020-07-13T04:56:01Z

android-如何生成一定范围内的随机数?

如何创建使用Eclipse在Android中生成随机数,然后在TextView字段中显示结果的应用程序? 随机数必须在用户选择的范围内。 因此,用户将输入范围的最大值和最小值,然后输出答案。

trans by 2020-07-09T15:54:04Z

python-处理在gen中引发的异常

我有一个生成器和一个使用它的函数:

def read():
    while something():
        yield something_else()

def process():
    for item in read():
        do stuff

如果生成器引发异常,我想在使用者函数中处理该异常,然后继续使用迭代器,直到耗尽为止。 请注意,我不想在生成器中有任何异常处理代码。

我想到了类似的东西:

reader = read()
while True:
    try:
        item = next(reader)
    except StopIteration:
        break
    except Exception as e:
        log error
        continue
    do_stuff(item)

但这对我来说看起来很尴尬。

trans by 2020-07-06T15:29:11Z

从Python列表中获取前n个唯一元素

我有一个python列表,其中元素可以重复。

>>> a = [1,2,2,3,3,4,5,6]

我想从列表中获得第一个n个独特元素。因此,在这种情况下,如果我想要前5个唯一元素,它们将是:

[1,2,3,4,5]

我想出了一个使用生成器的解决方案:

def iterate(itr, upper=5):

    count = 0
    for index, element in enumerate(itr):
        if index==0:
            count += 1
            yield element

        elif element not in itr[:index] and count<upper:
            count += 1
            yield element

正在使用:

>>> i = iterate(a, 5)
>>> [e for e in i]
[1,2,3,4,5]

我怀疑这是否是最佳解决方案。 有没有一种我可以实现的替代策略,可以用更加Python化和高效的方式编写它方式?

trans by 2020-06-30T05:01:42Z

返回生成器以及Python 3.3中的yield

在Python 2中,函数定义中return和yield一起出现错误。 但是对于Python 3.3中的这段代码

def f():
  return 3
  yield 2

x = f()
print(x.__next__())

没有错误,return与函数一起使用yield。 但是,当调用函数__next__时,将引发StopIteration异常。 为什么不仅有返回值3? 这个回报以某种方式被忽略了吗?

trans by 2020-06-26T18:54:40Z

python 2.7-我应该如何使用Google样式的Sphinx记录列表,可选内容和收益?

如何使用Sphinx-Napoleon在Google样式的文档字符串上指示列表类型,可选参数和生成器的返回类型?

我试过了

List[type]
list of type

Optional[type]
type, optional

Yields:
   type: 

分别; 但是所有生成的输出都不令人满意,这与生成的文档的其余部分不一致。 例如

Optional[type]

只是给

可选[类型]

没有type的任何链接。

我尝试了所有内置主题,并且遇到了相同的问题。

我应该如何在Sphinx-Napoleon中使用Google样式的文档字符串记录这些元素?

trans by 2020-06-22T07:08:25Z

generator-node.js是否支持yield?

有什么方法可以让生成器进入node.js?

我目前在用回调伪造它们,但我必须记住检查生成器函数内部的回调响应,这会产生大量if (callback(arg) === false) return;

我想要类似python的内容:

for p in primes():
  if p > 100: break
  do_something(p)

我正在像这样在节点中做的事情:

primes(function(p) {
  if (p > 100) return false;
  do_something(p)
});

也许像coffeescript这样的东西可以帮助您?

trans by 2020-06-21T06:09:25Z

我如何判断发电机是否刚刚启动?

我想要一个函数.gi_running,该函数的行为如下:

>>> def gen(): yield 0; yield 1
>>> a = gen()
>>> is_just_started(a) 
True
>>> next(a)
0
>>> is_just_started(a) 
False
>>> next(a)
1
>>> is_just_started(a) 
False
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> is_just_started(a)
False

如何实现此功能?

我查看了.gi_running属性,但它似乎用于其他用途。

如果我知道需要发送到生成器的第一个值,则可以执行以下操作:

def safe_send(gen, a):
    try:
        return gen.send(a)
    except TypeError as e:
        if "just-started" in e.args[0]:
            gen.send(None)
            return gen.send(a)
        else:
            raise

但是,这似乎很可恶。

trans by 2020-02-04T08:08:45Z

python-generator.throw()有什么用?

PEP 342(通过增强型生成器进行协程)向生成器对象添加了throw()方法,该方法允许调用方在生成器内引发异常(就像它是由yield表达式抛出的一样)。

我想知道此功能的用例是什么。

trans by 2020-02-04T05:57:52Z

如何克隆Python生成器对象?

考虑这种情况:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os

walk = os.walk('/home')

for root, dirs, files in walk:
    for pathname in dirs+files:
        print os.path.join(root, pathname)

for root, dirs, files in walk:
    for pathname in dirs+files:
        print os.path.join(root, pathname)

我知道这个示例有点多余,但是您应该考虑到我们需要多次使用相同的walk2 = walk数据。 我有一个基准场景,必须使用相同的walk数据才能获得有用的结果。

我已经尝试在第二个迭代中克隆和使用walk2 = walk,但没有成功。 问题是...我该如何复制? 有可能吗?

先感谢您。

trans by 2020-01-30T06:33:32Z

generator-Python中的收益中断

根据对这个问题的回答,C#中的yield break等同于python中的return。 在正常情况下,“返回”确实会停止发电机。 但是,如果您的函数只执行返回操作,则将获得None而不是空的迭代器,该迭代器由C#中的yield break返回

def generate_nothing():
    return

for i in generate_nothing():
    print i

您将收到TypeError:'NoneType'对象不可迭代。但是,如果我在返回前添加了永不运行的收益,则此函数将返回我期望的结果。

def generate_nothing():
    if False: yield None
    return

如果可行,但似乎有线。 谁有更好的主意?

谢谢,

trans by 2020-01-29T09:42:13Z

python-列表字典的笛卡尔积

我正在尝试编写一些代码来测试一堆输入参数的笛卡尔积。

我看过itertools,但是它的product功能并不是我想要的。 是否有一种简单明了的简单方法来制作一个字典,每个字典中有任意数量的键和任意数量的元素,然后生成具有下一个排列的字典?

输入:

options = {"number": [1,2,3], "color": ["orange","blue"] }
print list( my_product(options) )

输出示例:

[ {"number": 1, "color": "orange"},
  {"number": 1, "color": "blue"},
  {"number": 2, "color": "orange"},
  {"number": 2, "color": "blue"},
  {"number": 3, "color": "orange"},
  {"number": 3, "color": "blue"}
]
trans by 2020-01-24T02:43:46Z

python-此lambda / yield / generator理解如何工作?

我今天在浏览我的代码库,发现了这一点:

def optionsToArgs(options, separator='='):
    kvs = [
        (
            "%(option)s%(separator)s%(value)s" %  
            {'option' : str(k), 'separator' : separator, 'value' : str(v)}
        ) for k, v in options.items()
    ]
    return list(
        reversed(
            list(
                    (lambda l, t: 
                        (lambda f: 
                            (f((yield x)) for x in l)
                        )(lambda _: t)
                    )(kvs, '-o')
                )
            )
        )

似乎要听一些参数,然后将它们变成shell命令的参数列表。 看来它正在生成器理解中使用yield,我认为这是不可能的...?

>>> optionsToArgs({"x":1,"y":2,"z":3})
['-o', 'z=3', '-o', 'x=1', '-o', 'y=2']

它是如何工作的?

trans by 2020-01-24T02:28:29Z

javascript-检查函数是否为gen

我在Nodejs v0.11.2中使用了生成器,我想知道如何检查函数的自变量是生成器函数。

我找到了typeof f === 'function' && Object.getPrototypeOf(f) !== Object.getPrototypeOf(Function)的这种方式,但是我不确定这是否很好(并且将来会继续工作)。

您对此问题有何看法?

trans by 2020-01-05T22:18:10Z

在Python中获取生成器的第n个项

有没有一种语法更简洁的方式编写以下内容?

gen = (i for i in xrange(10))
index = 5
for i, v in enumerate(gen):
    if i is index:
        return v

生成器应该具有gen[index]表达式,这似乎是很自然的,该表达式充当列表,但在功能上与上述代码相同。

trans by 2020-01-02T11:12:47Z

generator-Python中yield表达式的结果是什么?

我知道yield将函数转换为生成器,但是yield表达式本身的返回值是多少? 例如:

def whizbang(): 
    for i in range(10): 
        x = yield i

执行此函数时变量x的值是什么?

我已经阅读了Python文档:[http://docs.python.org/reference/simple_stmts.html#grammar-token-yield_stmt],并且似乎没有提及yield表达式本身的值。

trans by 2019-12-24T18:48:02Z

1 2 3 4 下一页 共4页