Re: Using my routines as functions AND methods

2024-01-04 Thread Thomas Passin via Python-list

On 1/3/2024 8:00 PM, Alan Gauld via Python-list wrote:

On 03/01/2024 22:47, Guenther Sohler via Python-list wrote:

Hi,

In my cpython i have written quite some functions to modify "objects".
and their python syntax is e.g.\

translate(obj, vec). e.g whereas obj is ALWAYS first argument.



However, I also want to use these functions as class methods without having
to
write the function , twice. When using the SAME function as a methos, the
args tuple must insert/contain "self" in the first location, so i have
written a function to do that:


I'm probably missing something obvious here but can't you
just assign your function to a class member?

def myFunction(obj, ...): ...

class MyClass:
 myMethod = myFunction


Then you can call it as

myObject = MyClass()
myObject.myMethod()

A naive example seems to work but I haven't tried anything
complex so there is probably a catch. But sometimes the simple
things just work?


That works if you assign the function to a class instance, but not if 
you assign it to a class.


def f1(x):
print(x)
f1('The plain function')

class Class1:
pass

class Class2:
pass

c1 = Class1()
c1.newfunc = f1
c1.newfunc('f1 assigned to instance') # Works as intended

Class2.newfunc = f1
c2 = Class2()
c2.newfunc('f1 assigned to class')  # Complains about extra argument


--
https://mail.python.org/mailman/listinfo/python-list


Re: Using my routines as functions AND methods

2024-01-04 Thread Alan Gauld via Python-list
On 04/01/2024 04:17, Thomas Passin via Python-list wrote:

>> I'm probably missing something obvious here but can't you
>> just assign your function to a class member?
>>
>> def myFunction(obj, ...): ...
>>
>> class MyClass:
>>  myMethod = myFunction
> 
> That works if you assign the function to a class instance, but not if 
> you assign it to a class.
> 
> def f1(x):
>  print(x)
> f1('The plain function')
> 
> class Class1:
>  pass
> 
> class Class2:
>  pass
> 
> c1 = Class1()
> c1.newfunc = f1
> c1.newfunc('f1 assigned to instance') # Works as intended
> 
> Class2.newfunc = f1
> c2 = Class2()
> c2.newfunc('f1 assigned to class')  # Complains about extra argument

Yes but I did the assignment inside the class definition and
that seemed to work just fine:

>>> def g(obj, st): print(st, obj.v)
...
>>> class D:
...def __init__(self,v): self.v = v
...m = g
...
>>> d = D(66)
>>> g(d,'val = ')
val =  66
>>> d.m('v = ')
v =  66


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Using my routines as functions AND methods

2024-01-04 Thread Guenther Sohler via Python-list
Hi list

The approach with defining the methods from python appears to be a very
good idea and it also works for classes, defined in python side.
However, when I try this one:

def mytrans(self):
print(self)

c=cube()
cls=c.__class__

cls.trans=mytrans

I get this:

Traceback (most recent call last):

File "", line 8, in 

TypeError: cannot set 'trans' attribute of immutable type 'PyOpenSCAD'

The Problem is probably that PyOpenSCAD is a class not defined on python
side but on c++ side,
 I fear that I need to solution in c++ side. ...



On Wed, Jan 3, 2024 at 11:47 PM Guenther Sohler 
wrote:

> Hi,
>
> In my cpython i have written quite some functions to modify "objects".
> and their python syntax is e.g.\
>
> translate(obj, vec). e.g whereas obj is ALWAYS first argument.
>
> on c side this functions looks like:
> PyObject *python_translate(PyObject *self, PyObject *args, PyObject
> *kwargs)
>
> this works great when specifying a list of functions in PyModuleDef
> structure.
>
> However, I also want to use these functions as class methods without
> having to
> write the function , twice. When using the SAME function as a methos, the
> args tuple must insert/contain "self" in the first location, so i have
> written a function to do that:
>
> PyObject *python_oo_args(PyObject *self, PyObject *args) // returns new
> reference,
> {
>   int i;
>   PyObject *item;
>   int n = PyTuple_Size(args);
>   PyObject *new_args = PyTuple_New(n + 1);
>   PyTuple_SetItem(new_args, 0, self);
>
>   for (i = 0; i < PyTuple_Size(args); i++) {
> item = PyTuple_GetItem(args, i);
> PyTuple_SetItem(new_args, i + 1, item);
>   }
>   return new_args;
> }
>
> To fill in method array, i have created a #define like this:
>
> #define OO_METHOD_ENTRY(name,desc) \
>   { #name, (PyCFunction) ( [ ] (PyObject *self, PyObject *args) ->
> PyObject * { \
>   PyObject *new_args = python_oo_args(self, args); \
>   PyObject *result = python_##name(self, new_args, NULL); \
>   return result;  } ),  METH_VARARGS | METH_KEYWORDS, (desc)},
>
> (this uses a lambda function)
>
> and use this in the array as:
>
> PyMethodDef PyOpenSCADMethods[] = {
>   OO_METHOD_ENTRY(translate,"Move Object")
>   OO_METHOD_ENTRY(right,"Right Object")
>
> Using this  i can reuse all the functions as methods,
> but its not 100% stable/bulletproof and crashes sometimes.
> So there is the bug ?
> Is there a better approach to reach my goal ?
>
>
> thank you
>
>
-- 
https://mail.python.org/mailman/listinfo/python-list