Why this works :
In [1]: def new_class(klass):
...: globals()[klass] = type(klass, (object,), {})
...:
In [2]: new_class('AA')
In [3]: AA()
Out[3]: <__main__.AA at 0x7f5629c5ddc0>
But when it is from module it doesnt ??
In [4]: from maker import *
In [5]: new_class2??
Signature: new_class2(klass)
Docstring: <no docstring>
Source:
def new_class2(klass):
globals()[klass] = type(klass, (object,), {})
File: /my/py38/seq2struct/lib/maker.py
Type: function
In [6]: new_class2('AB')
In [7]: AB()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [7], in <cell line: 1>()
----> 1 AB()
NameError: name 'AB' is not defined
The problems is that globals() returns the dictionary implementing the current module namespace. (see here)
new_class2 is defined in a different module, therefore it is modifying the globals of that module.
I see, so the solution is
In [10]: import maker
In [11]: maker.AB()
Out[11]: <maker.AB at 0x7f5629bbe370>
Related
x = Symbol ("x")
f = log(x)
dif1 = diff(f,x)
dif2 = diff(dif1,x)
dif3 = diff(dif2,x)
dif4 = diff(dif3,x)
dif5 = diff(dif4,x)
def D11(a,h):
return (f.evalf(subs={x:a+h})-f.evalf(subs={x:a}))/h + (h/2)*dif2.evalf(subs={x:a+h/2})
def D12(a,h):
return ((f.evalf(subs={x:(a+h)}) - f(a-h)))/(2*h) - h**2/6*dif3.evalf(subs={x:(a)})
def D13(a,h):
return (f.evalf(subs={x:(a-2*h)})- 8*f.evalf(subs={x:(a-h)}) + 8*f.evalf(a+h) - f(a+2*h))/(12*h) - h**4/30*ftuletis5(a)
def D22(a,h):
return (f.evalf(subs={x:(a+h)}) - 2*f.evalf(subs={x:(a)}) + f.evalf(subs={x:(a-h)}))/h**2 - h**2/12*(dif4.evalf(subs={x:(a)}))
vigaD11 = []
vigaD12 = []
vigaD13 = []
vigaD22 = []
h=[]
for i in range(20):
h+=h+[(10**(-i))]
vigaD11+= vigaD11 + [(D11(2,h[i])-(dif1.evalf(subs={x:2})))]
vigaD12+= vigaD12+[(D12(2,h[i])-(dif1.evalf(subs={x:2})))]
vigaD13+= vigaD13 + [(D13(2,h[i])-(dif1.evalf(subs={x:2})))]
vigaD22+= vigaD22 [(D22(2,h[i])-(dif2.evalf(subs={x:2})))]
I get an error message saying that log object is not callable. Currently I'm using the math package and Sympy package to get the program to do what I want.
The error message I get:
Traceback (most recent call last):
File "C:\Users\arman\Desktop\Numbrilised meetodid\praktikum12\praktikum12.py", line 64, in <module>
vigaD12+= vigaD12+[(D12(2,h[i])-(dif1.evalf(subs={x:2})))]
File "C:\Users\arman\Desktop\Numbrilised meetodid\praktikum12\praktikum12.py", line 37, in D12
return ((f.evalf(subs={x:(a+h)}) - f(a-h)))/(2*h) - h**2/6*dif3.evalf(subs={x:(a)})
TypeError: 'log' object is not callable
It still does not work when I specifically call out the sympy version of log. Please help.
You could try f = math.log(x) or whichever log function you want to use. Maybe python just doesn't find the right function to call.
In an isympy session with * import ofsympyandxsymbol,log` a sympy object
In [1]: log
Out[1]: log
In [2]: x
Out[2]: x
In [3]: f = log(x)
In [4]: f(23)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-a73e6f7d2549> in <module>
----> 1 f(23)
TypeError: 'log' object is not callable
You can't call log again; it's already been "called". You can evaluate it at specific number with:
In [13]: f.evalf(subs={x:1.23})
Out[13]: 0.207014169384326
You do that once in the problem expression, but not the second time. Why not?
f.evalf(subs={x:(a+h)}) - f(a-h)
How can I clear all the attributes off an instance of Python's threading.local()?
You can clear it's underlying __dict__:
>>> l = threading.local()
>>> l
<thread._local object at 0x7fe8d5af5fb0>
>>> l.ok = "yes"
>>> l.__dict__
{'ok': 'yes'}
>>> l.__dict__.clear()
>>> l.__dict__
{}
>>> l.ok
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'thread._local' object has no attribute 'ok'
Accessing the __dict__ directly is specifically called out as a valid way to interact with the local object in the _threading_local module documentation:
Thread-local objects support the management of thread-local data.
If you have data that you want to be local to a thread, simply create
a thread-local object and use its attributes:
>>> mydata = local()
>>> mydata.number = 42
>>> mydata.number
42
You can also access the local-object's dictionary:
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]
I'm using BeautifulSoup to do some crawling, and want to chain find calls, for example:
soup.find('div', class_="class1").find('div', class_="class2").find('div', class_="class3")
Of course, this breaks whenever one of the divs cannot be found, throwing an
AttributeError: 'NoneType' object has no attribute 'find'
Is there a way to modify NoneType to add a find method such as
class NoneType:
def find(*args):
return None
so that I can do something like
thing = soup.find('div', class_="class1").find('div', class_="class2").find('div', class_="class3")
if thing:
do more stuff
instead of
thing1 = soup.find('div', class_="class1")
if thing1:
thing2 = thing1.find('div', class_="class2")
if thing2:
thing3 = thing2.find('div', class_="class3")
etc.
I think I might be able to do something similar by using a parser with XPath capabilities, but the question is not specific to this use case and is more about modifying/overriding built in classes.
Why not use a try/except statement instead (since you cannot modify NoneType)?
try:
thing = soup.find('div', class_="class1").find('div', class_="class2").find('div', class_="class3")
do more stuff
except AttributeError:
thing = None # if you need to do more with thing
You can't modify builtin class such as NoneType or str:
>>> nt = type(None)
>>> nt.bla = 23
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'NoneType'
For some of them (eg str), you can inherit from:
>>> class bla(str):
... def toto(self): return 1
>>> bla('2123').toto()
1
It's not possible with NoneType. And it won't help you either:
>>> class myNoneType(nt):
... def find(self): return 1
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'NoneType' is not an acceptable base type
You cannot modify the class and the real question is why you would try? NoneType means there is no data there so when you attempt a .find() on that type even if it did exist you would only get null or no values from it. I would reccomend something like this.
try:
var = soup.find('div', class_="class1").find('div', class_="class2").find('div', class_="class3")
except AttributeError:
do something else instead or message saying there was no div
You can't inherit from None:
>>> class Noneish(type(None)):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'NoneType' is not an acceptable base type
An approach might be to have a
class FindCaller(object):
def __init__(self, *a, **k):
self.a = a
self.k = k
def __call__(self, obj):
return obj.find(*self.a, **self.k)
def callchain(root, *fcs):
for fc in fcs:
root = fc(root)
if root is None: return
return root
and then do
thing = callchain(soup,
FindCaller('div', class_="class1"),
FindCaller('div', class_="class2"),
FindCaller('div', class_="class3"),
)
You can't. For good reasons...
In fact, NoneType is even less accessible than other built-in types:
type(None).foo = lambda x: x
# ---------------------------------------------------------------------------
# TypeError Traceback (most recent call last)
# <ipython-input-12-61bbde54e51b> in <module>()
# ----> 1 type(None).foo = lambda x: x
# TypeError: can't set attributes of built-in/extension type 'NoneType'
NoneType.foo = lambda x: x
# ---------------------------------------------------------------------------
# NameError Traceback (most recent call last)
# <ipython-input-13-22af1ed98023> in <module>()
# ----> 1 NoneType.foo = lambda x: x
# NameError: name 'NoneType' is not defined
int.foo = lambda x: x
# ---------------------------------------------------------------------------
# TypeError Traceback (most recent call last)
# <ipython-input-14-c46c4e33b8cc> in <module>()
# ----> 1 int.foo = lambda x: x
# TypeError: can't set attributes of built-in/extension type 'int'
As suggested above, use try: ... except AttributeError: clause.
>>> FooChild = type("FooChild", (Foo,), {"echobar()":echo_bar})
>>> FooChild().echobar()
Traceback (most recent call last):
File "<pyshell#214>", line 1, in <module>
FooChild().echobar()
AttributeError: 'FooChild' object has no attribute 'echobar'
>>> FooChild().echobar
Traceback (most recent call last):
File "<pyshell#215>", line 1, in <module>
FooChild().echobar
AttributeError: 'FooChild' object has no attribute 'echobar'
>>> hasattr(FooChild, "echobar()")
True
>>> FooChild().echobar()()
Traceback (most recent call last):
File "<pyshell#217>", line 1, in <module>
FooChild().echobar()()
AttributeError: 'FooChild' object has no attribute 'echobar'
Remove those parentheses:
FooChild = type("FooChild", (Foo,), {"echobar":echo_bar})
The name of a function is without the parentheses. Appending them means to call the function. Without the parentheses you have a reference on the function itself (e. g. for passing a function to things like sort or map).
echobar() is an invalid identifier in python, so you can't access it directly i.e using the dot syntax:
>>> FooChild = type("FooChild", (Foo,), {"echobar()":10})
Use __dict__ or getattr:
>>> FooChild.__dict__['echobar()']
10
>>> getattr(FooChild, 'echobar()')
10
If you want to use it as an attribute then simply get rid of the parenthesis:
>>> FooChild = type("FooChild", (Foo,), {"echobar":10})
>>> FooChild.echobar
10
If you want to use it as a method, then:
>>> def echobar(self):return 10
>>> FooChild = type("FooChild", (Foo,), {'echobar':echobar})
>>> FooChild().echobar()
10
If you pretend to have fancy function with name echobar() in you class, only mean of accessing it is getattr:
class Foo(object):pass
echo_bar =lambda *a: 'bar'
FooChild = type("FooChild", (Foo,), {"echobar()":echo_bar})
print getattr(FooChild(), 'echobar()')()
# bar
Is it possible to run a function that is specified by using the magic %paste% function in IPython?
In [1]: %paste%
def add_to_index(index,keyword,url):
for e in index:
if e[0] == keyword:
if url not in e[1]:
e[1].append(url)
return
index.append([keyword,[url]])
## -- End pasted text --
Block assigned to '%'
In [2]: %whos
Variable Type Data/Info
-----------------------------
% SList ['def add_to_index(index,<...>append([keyword,[url]])']
In [3]: add_to_index
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-e3075a18cb0c> in <module>()
----> 1 add_to_index
NameError: name 'add_to_index' is not defined
In [4]: add_to_index(index, 'test', 'http://test.com')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-4-580237464b17> in <module>()
----> 1 add_to_index(index, 'test', 'http://test.com')
NameError: name 'add_to_index' is not defined
In [5]:
The paste magic is %paste (no trailing %):
In [3]: %paste
def add_to_index(index,keyword,url):
for e in index:
if e[0] == keyword:
if url not in e[1]:
e[1].append(url)
return
index.append([keyword,[url]])
## -- End pasted text --
In [4]: add_to_index
Out[4]: <function __main__.add_to_index>
What happens in your case is that you are using the optional argument for %paste:
In [5]: %paste?
Type: Magic function
...(text omitted)
You can also pass a variable name as an argument, e.g. '%paste foo'.
This assigns the pasted block to variable 'foo' as string, without
dedenting or executing it (preceding >>> and + is still stripped)
When you do that the pasted code does not get executed, it is just assigned to the variable you gave as an argument (% in your case).