Add PyTuple::to_list
This commit is contained in:
parent
30521c853d
commit
2c11b25fee
|
@ -1,7 +1,7 @@
|
||||||
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
|
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{PySequence, PyTuple};
|
use pyo3::types::{PyList, PySequence, PyTuple};
|
||||||
|
|
||||||
fn iter_tuple(b: &mut Bencher<'_>) {
|
fn iter_tuple(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
|
@ -61,6 +61,28 @@ fn sequence_from_tuple(b: &mut Bencher<'_>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tuple_new_list(b: &mut Bencher<'_>) {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
const LEN: usize = 50_000;
|
||||||
|
let tuple = PyTuple::new(py, 0..LEN);
|
||||||
|
b.iter(|| {
|
||||||
|
let _pool = unsafe { py.new_pool() };
|
||||||
|
let _ = PyList::new(py, tuple);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tuple_to_list(b: &mut Bencher<'_>) {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
const LEN: usize = 50_000;
|
||||||
|
let tuple = PyTuple::new(py, 0..LEN);
|
||||||
|
b.iter(|| {
|
||||||
|
let _pool = unsafe { py.new_pool() };
|
||||||
|
let _ = tuple.to_list();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn criterion_benchmark(c: &mut Criterion) {
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
c.bench_function("iter_tuple", iter_tuple);
|
c.bench_function("iter_tuple", iter_tuple);
|
||||||
c.bench_function("tuple_new", tuple_new);
|
c.bench_function("tuple_new", tuple_new);
|
||||||
|
@ -68,6 +90,8 @@ fn criterion_benchmark(c: &mut Criterion) {
|
||||||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||||
c.bench_function("tuple_get_item_unchecked", tuple_get_item_unchecked);
|
c.bench_function("tuple_get_item_unchecked", tuple_get_item_unchecked);
|
||||||
c.bench_function("sequence_from_tuple", sequence_from_tuple);
|
c.bench_function("sequence_from_tuple", sequence_from_tuple);
|
||||||
|
c.bench_function("tuple_new_list", tuple_new_list);
|
||||||
|
c.bench_function("tuple_to_list", tuple_to_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(benches, criterion_benchmark);
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
|
1
newsfragments/3044.added.md
Normal file
1
newsfragments/3044.added.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Add `PyTuple::to_list()`, as a convenient and efficient conversion from tuples to lists.
|
|
@ -6,6 +6,7 @@ use crate::ffi::{self, Py_ssize_t};
|
||||||
#[cfg(feature = "experimental-inspect")]
|
#[cfg(feature = "experimental-inspect")]
|
||||||
use crate::inspect::types::TypeInfo;
|
use crate::inspect::types::TypeInfo;
|
||||||
use crate::internal_tricks::get_ssize_index;
|
use crate::internal_tricks::get_ssize_index;
|
||||||
|
use crate::types::PyList;
|
||||||
use crate::types::PySequence;
|
use crate::types::PySequence;
|
||||||
use crate::{
|
use crate::{
|
||||||
exceptions, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, Py, PyAny, PyErr, PyObject,
|
exceptions, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, Py, PyAny, PyErr, PyObject,
|
||||||
|
@ -213,6 +214,15 @@ impl PyTuple {
|
||||||
length: self.len(),
|
length: self.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a new list containing the contents of this tuple; equivalent to the Python expression `list(tuple)`.
|
||||||
|
///
|
||||||
|
/// This method is equivalent to `self.as_sequence().list()` and faster than `PyList::new(py, self)`.
|
||||||
|
pub fn to_list(&self) -> &PyList {
|
||||||
|
self.as_sequence()
|
||||||
|
.list()
|
||||||
|
.expect("failed to convert tuple to list")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index_impls!(PyTuple, "tuple", PyTuple::len, PyTuple::get_slice);
|
index_impls!(PyTuple, "tuple", PyTuple::len, PyTuple::get_slice);
|
||||||
|
@ -444,7 +454,7 @@ tuple_conversion!(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::types::{PyAny, PyTuple};
|
use crate::types::{PyAny, PyList, PyTuple};
|
||||||
use crate::{Python, ToPyObject};
|
use crate::{Python, ToPyObject};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
@ -918,4 +928,14 @@ mod tests {
|
||||||
"Some destructors did not run"
|
"Some destructors did not run"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tuple_to_list() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let tuple = PyTuple::new(py, vec![1, 2, 3]);
|
||||||
|
let list = tuple.to_list();
|
||||||
|
let list_expected = PyList::new(py, vec![1, 2, 3]);
|
||||||
|
assert!(list.eq(list_expected).unwrap());
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue