diff --git a/src/instance.rs b/src/instance.rs index 0e704358..a8c0997b 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -534,6 +534,25 @@ impl Py { /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. + /// + /// If calling this method becomes performance-critical, the [`intern!`] macro can be used + /// to intern `attr_name`, thereby avoiding repeated temporary allocations of Python strings. + /// + /// # Example: `intern!`ing the attribute name + /// + /// ``` + /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPy, Py, Python, PyObject, PyResult}; + /// # + /// #[pyfunction] + /// fn version(sys: Py, py: Python<'_>) -> PyResult { + /// sys.getattr(py, intern!(py, "version")) + /// } + /// # + /// # Python::with_gil(|py| { + /// # let sys = py.import("sys").unwrap().into_py(py); + /// # version(sys, py).unwrap(); + /// # }); + /// ``` pub fn getattr(&self, py: Python<'_>, attr_name: N) -> PyResult where N: ToPyObject, @@ -546,6 +565,25 @@ impl Py { /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. + /// + /// If calling this method becomes performance-critical, the [`intern!`] macro can be used + /// to intern `attr_name`, thereby avoiding repeated temporary allocations of Python strings. + /// + /// # Example: `intern!`ing the attribute name + /// + /// ``` + /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPy, PyObject, Python, PyResult}; + /// # + /// #[pyfunction] + /// fn set_answer(ob: PyObject, py: Python<'_>) -> PyResult<()> { + /// ob.setattr(py, intern!(py, "answer"), 42) + /// } + /// # + /// # Python::with_gil(|py| { + /// # let ob = PyModule::new(py, "empty").unwrap().into_py(py); + /// # set_answer(ob, py).unwrap(); + /// # }); + /// ``` pub fn setattr(&self, py: Python<'_>, attr_name: N, value: V) -> PyResult<()> where N: ToPyObject, diff --git a/src/types/any.rs b/src/types/any.rs index 4e13b3e9..9ba9b515 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -111,6 +111,25 @@ impl PyAny { /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. + /// + /// If calling this method becomes performance-critical, the [`intern!`] macro can be used + /// to intern `attr_name`, thereby avoiding repeated temporary allocations of Python strings. + /// + /// # Example: `intern!`ing the attribute name + /// + /// ``` + /// # use pyo3::{intern, pyfunction, types::PyModule, PyAny, Python, PyResult}; + /// # + /// #[pyfunction] + /// fn version(sys: &PyModule) -> PyResult<&PyAny> { + /// sys.getattr(intern!(sys.py(), "version")) + /// } + /// # + /// # Python::with_gil(|py| { + /// # let sys = py.import("sys").unwrap(); + /// # version(sys).unwrap(); + /// # }); + /// ``` pub fn getattr(&self, attr_name: N) -> PyResult<&PyAny> where N: ToPyObject, @@ -124,6 +143,25 @@ impl PyAny { /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. + /// + /// If calling this method becomes performance-critical, the [`intern!`] macro can be used + /// to intern `attr_name`, thereby avoiding repeated temporary allocations of Python strings. + /// + /// # Example: `intern!`ing the attribute name + /// + /// ``` + /// # use pyo3::{intern, pyfunction, types::PyModule, PyAny, Python, PyResult}; + /// # + /// #[pyfunction] + /// fn set_answer(ob: &PyAny) -> PyResult<()> { + /// ob.setattr(intern!(ob.py(), "answer"), 42) + /// } + /// # + /// # Python::with_gil(|py| { + /// # let ob = PyModule::new(py, "empty").unwrap(); + /// # set_answer(ob).unwrap(); + /// # }); + /// ``` pub fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: ToBorrowedObject,