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 pyo3::prelude::*;
|
||||
use pyo3::types::{PySequence, PyTuple};
|
||||
use pyo3::types::{PyList, PySequence, PyTuple};
|
||||
|
||||
fn iter_tuple(b: &mut Bencher<'_>) {
|
||||
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) {
|
||||
c.bench_function("iter_tuple", iter_tuple);
|
||||
c.bench_function("tuple_new", tuple_new);
|
||||
|
@ -68,6 +90,8 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||
c.bench_function("tuple_get_item_unchecked", tuple_get_item_unchecked);
|
||||
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);
|
||||
|
|
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")]
|
||||
use crate::inspect::types::TypeInfo;
|
||||
use crate::internal_tricks::get_ssize_index;
|
||||
use crate::types::PyList;
|
||||
use crate::types::PySequence;
|
||||
use crate::{
|
||||
exceptions, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, Py, PyAny, PyErr, PyObject,
|
||||
|
@ -213,6 +214,15 @@ impl PyTuple {
|
|||
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);
|
||||
|
@ -444,7 +454,7 @@ tuple_conversion!(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{PyAny, PyTuple};
|
||||
use crate::types::{PyAny, PyList, PyTuple};
|
||||
use crate::{Python, ToPyObject};
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
@ -918,4 +928,14 @@ mod tests {
|
|||
"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