I'm trying to run a basic MATLAB script that defines a class, and get that class object returned to python. I don't know MATLAB well, and am very new to Oct2Py so I may be completely misunderstanding how to do this. Any help would be greatly appreciated.
Here is the Matlab file (taken from here)
classdef BasicClass
properties
Value {mustBeNumeric}
end
methods
function r = roundOff(obj)
r = round([obj.Value],2);
end
function r = multiplyBy(obj,n)
r = [obj.Value] * n;
end
end
end
And I call this in the python script with the following
from oct2py import octave
octave.addpath(r'C:\Users\i13500020\.spyder-py3\IST')
oclass = octave.class_example(nout=1)
when I run this I get a warning that prints four times and then an error message
First:
warning: struct: converting a classdef object into a struct overrides the access restrictions defined for properties. All properties are returned, including private and protected ones.
And then:
TypeError: 'NoneType' object is not iterable
I don't have any trouble running the roundtrip example from the Oct2Py page, so I know my installation is fine
I've written a small work around to use custom matlab classes with oct2py.
Currently, this approach supports only access to member functions (and not attributes) of the Matlab class as this was what I needed:
from oct2py import octave
class MatlabClass():
_counter = 0
def __init__(self, objdef) -> None:
"""Use matlab object as python class.
Args:
objdef (str): Class initialization as string.
"""
MatlabClass._counter += 1
self.name = f"object_for_python{MatlabClass._counter}"
octave.eval(f"{self.name} = {objdef};")
def __getattr__(self, item):
"""Maps values to attributes.
Only called if there *isn't* an attribute with this name
"""
def f(*args):
call = f"{self.name}.{item}({','.join([str(arg) for arg in args])});"
return octave.eval(call)
return f
use this class as followed:
param = 0.24 # random value you might need for class initialization
oclass = MatlabClass(f"BasicClass({param})")
x = oclass.roundOff()
y = oclass.multiplyBy(2)
Note: you might need an init function in your octave code to run set your Value variable.
Related
Background: I am working with the SymPy Module in jupyter notebooks. I want to create a sub/child class of the Matrix class of sympy (which is actually sympy.matrices.dense.MutableDenseMatrix).
I write this =>
import sympy as sym
class Mat(sym.Matrix):
def __init__(self,a):
self.a = super(a)
Then I call the following in a seperate cell
X=Mat([[1,2,3]])
This give an error
TypeError
Traceback (most recent call last)
<ipython-input-154-9d0dfad5081f> in <module>
----> 1 X= Mat([[1,2,3]])
<ipython-input-153-41d7b2cc4dd1> in __init__(self, a)
1 class Mat(sym.Matrix):
2 def __init__(self,a):
----> 3 self.a = super(a)
TypeError: super() argument 1 must be type, not list
Not knowing the cause of this I tried this
class Mat:
def __init__(self,a):
self.a = sym.Matrix(a)
then the assignment passed.
Now I ran this in the Next Cell alone (Let's say this is like just executing the Name for simplicity)
X
and got the output
<__main__.Mat at 0x7f80b77f8b80>
but I was expecting
[1 2 3]
or
Matrix([[1, 2, 3]])
These are the outputs that come in Jupyter Notebook and Python REPL respectively when I create a regular sym.Matrix object and just execute it's Name
Note: I know the existence of __str__ and __repr__ but those are helpful only if I use print(X)
Note: I tried definining __call__ as
def __call__(self):
return self.a
but it works only if I first execute X=X() then execute X
So My Question is, what is that internal method (maybe a magic method) that is called when executing just the Object Name and How do I define it for my class, if in future I create a class without inheritance (so I don't have to fallback on the super class method for the same)
By looking at the doc we have:
In Python, objects can declare their textual representation using the
_repr_ method. IPython expands on this idea and allows objects to declare other, rich representations including:
_repr_html_: return raw HTML as a string, or a tuple (see below).
_repr_json_: return a JSONable dict, or a tuple (see below).
_repr_jpeg_: return raw JPEG data, or a tuple (see below).
_repr_png_: return raw PNG data, or a tuple (see below).
_repr_svg_: return raw SVG data as a string, or a tuple (see below).
_repr_latex_: return LaTeX commands in a string surrounded by “$”, or a tuple (see below).
_repr_mimebundle_: return a full mimebundle containing the mapping
As an addition this SO question seems to be related.
A working snippet should be something like:
import sympy as sym
class Mat(sym.Matrix):
def __init__(self,a):
self.a = sym.Matrix(a)
def _repr_html_(self):
return f"<p><h1>{self.a.__repr__()}</h1></p>"
Which results in a similar output:
This question is related to these other posts on SO, yet the solutions suggested therein do not seem to work for my case. In short, my problem can be illustrated by the following example. I have an Algebra class where by the method triPower I aim at computing the power of a trinomial, i.e. (a+b+c)**n for many n values with fixed a, b, c. To do so, I thought of creating a method _triPower(a,b,c,n) and pass it to my pool.map() function by functools.partial(_triPower,...) where I fix a, b, c and leave n as the only parameter, since I am working in Python 2.7 and map from the multiprocessing module wants only one argument function (see otherwise this post). The code is the following:
from __future__ import division
import numpy as np
import functools as fntls
import multiprocessing as mp
import multiprocessing.pool as mppl
# A couple of classes introduced to allow multiple processes to have their own daemons (parallelization)
class NoDaemonProcess(mp.Process):
# make 'daemon' attribute always return False
def _get_daemon(self):
return False
def _set_daemon(self, value):
pass
daemon = property(_get_daemon, _set_daemon)
# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(mppl.Pool):
Process = NoDaemonProcess
# Sample class where I want a method to run a parallel loop
class Algebra(object):
def __init__(self,offset):
self.offset = offset
def trinomial(self,a,b,c):
return a+b+c
def _triPower(self,a,b,c,n):
"""This is the method that I want to run in parallel from the next method"""
return self.offset + self.trinomial(a,b,c)**n
def triPower(self,n):
pls = MyPool(4)
vals = pls.map(fntls.partial(self._triPower,a=1.,b=0.,c=1.),n)
print vals
# Testing
if __name__ == "__main__":
A = Algebra(0.)
A.triPower(np.arange(0.,10.,0.01))
The above does not work and produces (as expected from this post) the error:
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed
Hence, following the same post, I tried to define _triPower as a global function i.e.
def _triPower(alg,a,b,c,n):
"""This is the method that I want to run in parallel from the next method"""
return alg.trinomial(a,b,c)**n
and then editing Algebra.triPower(...) according to:
def triPower(self,n):
pls = MyPool(4)
vals = pls.map(fntls.partial(_triPower, alg=self, a=1., b=0., c=1.), n)
print vals
and this latter instead gives some weird TypeError like:
TypeError: _triPower() got multiple values for keyword argument 'alg'
On the other hand the suggestion to try to make the methods serializable by VeryPicklableObject as in this other post seems also not to work and this package appears dead by now (as of 05/2019). So what am I doing wrong and how can I make my computation run in parallel?
This question already has answers here:
How do I create a constant in Python?
(44 answers)
Closed 3 months ago.
I am writing a program in python which contains many constant variables. I would like to create a file that will hold all these variables like the .h file in C that contains many #define. I tried to use configparser however I didn't find it easy and fun to use.
Do you know a better way?
Python does not allow constant declarations like C or C++.
Normally in Python, constants are capitalized (PEP 8 standards) which helps the programmer know it's a constant.
Ex. MY_CONSTANT = "Whatever"
Another valid way of doing it which I don't use but heard of, is using a method:
def MY_CONSTANT():
return "Whatever"
Now in theory, calling MY_CONSTANT() acts just like a constant.
EDIT
Like the comments says, someone can go and change the value by calling
MY_CONSTANT = lambda: 'Something else'
but don't forget the same person can call MY_CONSTANT = "Something else" in the first example and change the initial value. In both cases it is unlikely but possible.
Constants (in a sense) in Python 3.8+
Python 3.8 introduces the typing.Final type qualifier, which is used to indicate that a variable or attribute should not be reassigned, redefined, or overridden.
PEP 591 -- Adding a final qualifier to typing
from typing import Final
# Annotate module variables
# (with or without an explicit type, using the syntax Final[<type>])
# (type is auto-determined in absence of an explicit type)
PI: Final[float] = 3.141592654
ANSWER_TO_EVERYTHING: Final = 42
# Annotate instance variables in class bodies
# (explicit type is needed if no value is assigned)
class Point:
x: Final[int]
y: Final = 0
def __init__(self, x: int):
self.x = x
# Annotate instance variables directly
# (only allowed in __init__ methods)
class Person:
def __init__(self, birth_year: int):
self.birth_year: Final = birth_year
Linters and type checkers will show you warnings if you reassign or redefine Final variables. Note that there is no runtime check, so you can still run the code below.
ANSWER_TO_EVERYTHING: Final = 42
ANSWER_TO_EVERYTHING = 420 # shows warning
print(ANSWER_TO_EVERYTHING) # prints 420
There is also the typing.final decorator, which is used to restrict inheriting classes and overriding methods.
There are no constants in Python, the way they exist in C or Java. You can imitate them by functions:
def FOO():
return "foo"
You can wrap the function call in a property, and thus make it look like a variable:
class Const:
#property
def FOO(self):
return "foo"
CONST = Const() # You need an instance
if something == CONST.FOO:
...
With a bit of meta stuff, one can get unsettable attributes with a terse syntax:
def const(cls):
# Replace a class's attributes with properties,
# and itself with an instance of its doppelganger.
is_special = lambda name: (name.startswith("__") and name.endswith("__"))
class_contents = {n: getattr(cls, n) for n in vars(cls) if not is_special(n)}
def unbind(value): # Get the value out of the lexical closure.
return lambda self: value
propertified_contents = {name: property(unbind(value))
for (name, value) in class_contents.items()}
receptor = type(cls.__name__, (object,), propertified_contents)
return receptor() # Replace with an instance, so properties work.
#const
class Paths(object):
home = "/home"
null = "/dev/null"
Now you can access Paths.home as a normal value, but can't assign to it. You can define several classes decorated with #const, as you might use several .h files.
You can use something like this:
Files structure:
myapp/
__init__.py
settings.py
main.py
settings.py
CONST_A = 'A'
CONST_B = 'B'
__init__.py
from . import settings as global_settings
class Settings:
def __init__(self):
for setting in dir(global_settings):
if setting.isupper():
setattr(self, setting, getattr(global_settings, setting))
def __setattr__(self, attr, value):
if not getattr(self, attr, None):
super().__setattr__(attr, value)
else:
raise TypeError("'constant' does not support item assignment")
settings = Settings()
main.py
import settings
print(settings.CONST_A) # prints A
settings.CONST_A = 'C' # raises TypeError error
print(settings.CONST_A) # prints A
settings.CONST_C = 'C' # also able to add new constants
print(settings.CONST_C) # prints C
Overwritten __setattr__ in Settings class makes all the attributes read-only.
The only requirement is to have all the constants in your settings.py written in capital letters.
But be aware, that it's not gonna work if you import variables directly:
from settings import CONST_A
print(settings.CONST_A) # prints A
settings.CONST_A = 'C' # sets C
print(settings.CONST_A) # prints C
Just define a constants.py file and write all your constants. There is no other magic trick in Python. Use caps as a general convention.
Python isn't preprocessed. You can just create a file constant.py
#!/usr/bin/env python
# encoding: utf-8
"""
constant.py
"""
MY_CONSTANT = 50
Import constant.py file when ever you want constant values like below example.
#!/usr/bin/env python
# encoding: utf-8
"""
example.py
"""
import constant
print constant.MY_CONSTANT * 2
This way you can use constants across project.
You also have the option, if the constants are tied to a particular class and used privately within that class of making them specific to that class:
class Foo(object):
GOOD = 0
BAD = 1
def __init__(self...
If you want to define and use entire module, making them on top of the module
PIE = 3.47
class Foo(object):
def __init__(self...
I'm trying add new methods dynamically in python in the constructor ...
Context
I wrote a Python module in C++ that interacts with my signal processing libraries written in C ...
I have generic method to access my modules (called filters) parameters.
Eg.:
int my_filter_set( void * filter_handle, const char * method_id, void * p_arg );
So my cpython wraps it like this :
filter.set(method_id,value)
And I have access to all my method ids.
>>> filter.setters
['SampleRate','...']
Goal
I would like to generate setters like :
>>> filter.setSampleRate(value)
in a derived class.
class Filter(BaseFilter):
'''
classdocs
'''
def __init__(self, name, library):
'''
Constructor
'''
BaseFilter.__init__(self,name,library)
for setter_id in self.setters:
code = 'self.set(' + setter_id + ',value)'
# #todo add the method body to a new method called 'set' + method_id (with 'value' as argument)
Questions are ...
Is it possible ?
With python types module ?
How to do it ?
I already checked this but I don't see the way I can adapt it to my purpose.
Thanks.
Rather than create the methods dynamically, you can check for method names that match your setters and then dispatch dynamically to your set() method. This can be achieved by overriding __getattribute__() in your Filter class:
class BaseFilter(object):
setters = ('SampleRate', 'Gain', 'BitDepth',)
def set(self, method_id, value):
print 'BaseFilter.set(): setting {} to {}'.format(method_id, value)
class Filter(BaseFilter):
def __getattribute__(self, name):
method_id = name.lstrip('set')
if name.startswith('set') and method_id in super(Filter, self).setters:
def _set(value):
return self.set(method_id, value)
return _set
else:
return super(Filter, self).__getattribute__(name)
Here, for methods that are to be dispatched to BaseFilter.set(), __getattribute__() returns a wrapped version of BaseFilter.set() that has access to the method_id in a closure.
>>> f = Filter()
>>> f.setSampleRate(44000)
BaseFilter.set(): setting SampleRate to 44000
>>> f.setBitDepth(16)
BaseFilter.set(): setting BitDepth to 16
>>> f.setGain(100)
BaseFilter.set(): setting Gain to 100
>>> f.setHouseOnFire(999)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in __getattribute__
AttributeError: 'Filter' object has no attribute 'setHouseOnFire'
I'm not sure if your setter method names are available before the class definition is first encountered, if so, using a meta class to create the class might be appropriate. If they're only available at runtime, then this answer should direct you the way to your solution: Adding a Method to an Existing Object Instance
From your description I cannot tell whether you looking for a way to create Python functions at run time or you're looking for a way to provide Python bindings for your existing code base. There are many ways to make your code available to Python programmers.
I have two modules called Dfs and Graph.
In my Graph module, I have a class Graph and a method called ReadGraph.
In my Dfs module, I have a method that calls on ReadGraph but I get the following error message when I type: Dfs.ProcessGraph(testcase.txt,verbose=True)
Error message:
NameError: name 'testcase' is not defined
Could someone explain how to fix this?
Thanks.
From my Dfs.py module:
import sys
from Graph import *
class Dfs( object ):
def ProcessGraph(file_name, verbose):
g=ReadGraph(file_name)
From my Graph.py module:
class Graph( object ):
def ReadGraph( file_name ):
Remove your class declaration from Graph.py. When you import all from a file you get all top level objects. In this case it's the Graph class itself, not its methods.
Also you need to pass string 'testcase.txt' not testcase.txt.
You have multiple problems here:
If you from Graph import * (which is bad practice to start with), you bring Graph into your name space. However, ReadGraph is inside Graph, so to access it you need Graph.ReadGraph.
Having done that, you try to call Dfs.ProcessGraph(testcase.txt,verbose=True). The first argument is interpreted as "pass the txt attribute of the object referenced by name testcase, which doesn't exist. Instead, you mean "testcase.txt" (quoted to make it a string).
Having done all of that, you get e.g. TypeError: unbound method ProcessGraph() must be called with Dfs instance as first argument (got str instance instead). When you call an instance method, the first argument, self by convention, is the instance itself. You have two choices; either a) make e.g. ProcessGraph a #staticmethod, and access it Graph.ReadGraph; or b) move it outside the class, then you can access it directly like you tried to in the first place. As you don't seem to have any class or instance attributes, it's not clear why you are bothering with the classes at all.
What it should probably look like:
import sys
from Graph import read_graph
def process_graph(file_name, verbose):
g = read_graph(file_name)
Graph.py module (note absence of class Graph):
def read_graph(file_name):
...
(Generally, I suggest you read PEP 8).
your code should be : Dfs.ProcessGraph('testcase.txt',verbose=True)
and not Dfs.ProcessGraph(testcase.txt,verbose=True)
'testcase.txt' # is a string and should be between quotes
also check if it is in the same directory where your code live else point to it
plus in DFs you should instantiate Graph :
from Graph.Graph import *
g = Graph()
grf = g.ReadGraph('filename')
EDIT: to be more precise
in Graph module:
class Graph(object):
def __init__(self):
pass # for the example now
def read_graph(self, file_name):
return file_name
in Dfs Module:
from Graph import *
class Dfs(object):
def __init__(self):
pass # for the example now
def ProcessGraph(file_name, verbose):
g = Graph()
file_name = Graph.read_graph(file_name)