Is there a way to create SimpleNamespace with boolean value false? - python

I am trying to create a SimpleNamespace with false value, but it is not working for me.
EMPTY = types.SimpleNamespace(__bool__=lambda self: False)
assert bool(EMPTY) == False # raises error!!
Is there a way to create SimpleNamespace with boolean value false?

It is not possible to give custom, "real" methods to individual instances of a class. In the original code, EMPTY.__bool__ is not a method, but an ordinary function. You can see this by trying to invoke it explicitly:
>>> EMPTY = types.SimpleNamespace(__bool__=lambda self: False)
>>> EMPTY.__bool__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'self'
See also Adding a Method to an Existing Object Instance. While it's possible - following the advice there - to make EMPTY.__bool__ behave like a method:
>>> EMPTY = types.SimpleNamespace()
>>> EMPTY.__bool__ = types.MethodType(lambda self: False, EMPTY)
>>> EMPTY.__bool__()
False
that will still be ignored by bool:
>>> bool(EMPTY)
True
The implementation of bool looks up __bool__ directly on the class, because it has no reason to expect an instance to have such an attribute.
Instead, we need to have our own class, with an actual method named __bool__ that does the right thing. Thus:
class PossiblyEmptyNamespace(types.SimpleNamespace):
"""A namespace that is falsey when it doesn't contain anything."""
def __bool__(self):
return bool(vars(self))
Now we can test that:
>>> EMPTY = PossiblyEmptyNamespace()
>>> bool(EMPTY)
False
>>> EMPTY.foo = 'bar'
>>> bool(EMPTY) # oops, not actually empty any more.
True

As mentioned in the comments, you'll need to make a subclass. Dunder methods like __bool__ are generally looked up on the class, not the specific instance, so setting a field on an instance will do you no good in this case.
from types import SimpleNamespace
class FalsyNamespace(SimpleNamespace):
def __bool__(self):
return False
EMPTY = FalsyNamespace()
assert bool(EMPTY) == False

Related

Strange behaviour of isinstance function

I have a class named Factor in the module Factor.py (https://github.com/pgmpy/pgmpy/blob/dev/pgmpy/factors/Factor.py) and also have function named factor_product in Factor.py as:
def factor_product(*args):
if not all(isinstance(phi, Factor) for phi in args):
raise TypeError("Input parameters must be factors")
return functools.reduce(lambda phi1, phi2: _bivar_factor_operation(phi1, phi2,
operation='M'), args)
Now if I even pass instances of Factor to the function, it still throws TypeError. A few lines from the debugger with breakpoint set just above the if statement:
(Pdb) args
args = (<pgmpy.factors.Factor.Factor object at 0x7fed0faf76a0>, <pgmpy.factors.Factor.Factor object at 0x7fed0faf7da0>)
(Pdb) isinstance(args[0], Factor)
False
(Pdb) type(args[0])
<class 'pgmpy.factors.Factor.Factor'>
(Pdb) Factor
<class 'pgmpy.factors.Factor.Factor'>
Any idea why this is happening ?
reload is a good way to end up with two copies of the same class from the same module: one from before the reload (if any instances of that class are still lurking about) and one from after.
Most likely you had objects of the new type, but Factor referred to the old type, since it was imported some time ago. So it's completely true that your objects aren't instances of Factor... not that Factor, anyway.
Never trust reload. :)
As isinstance Return true if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof , it just return true if you pass the instance of your class to it not the class itself , see the following example :
>>> class A :
... pass
...
>>> isinstance(A,A)
False
>>> isinstance(A(),A)
True
>>> z=A()
>>> isinstance(z,A)
True

None Python error/bug?

In Python you have the None singleton, which acts pretty oddly in certain circumstances:
>>> a = None
>>> type(a)
<type 'NoneType'>
>>> isinstance(a,None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
So first off, <type 'NoneType'> displays that None is not a type, but that NoneType is. Yet when you run isinstance(a,NoneType), it responds with an error: NameError: name 'NoneType' is not defined
Now, given this, if you have a function with an input default set to None, and need to check, you would do the following:
if variable is None:
#do something
else:
#do something
what is the reason that I cannot do the following instead:
if isinstance(variable,None): #or NoneType
#do something
else:
#do something
I am just looking for a detailed explanation so I can better understand this
Edit: good application
Lets say I wanted to use isinstance so that I can do something if variable is a variety of types, including None:
if isinstance(variable,(None,str,float)):
#do something
You can try:
>>> variable = None
>>> isinstance(variable,type(None))
True
>>> variable = True
>>> isinstance(variable,type(None))
False
isinstance takes 2 arguments isinstance(object, classinfo) Here, by passing None you are setting classinfo to None, hence the error. You need pass in the type.
None is not a type, it is the singleton instance itself - and the second argument of isinstance must be a type, class or tuple of them. Hence, you need to use NoneType from types.
from types import NoneType
print isinstance(None, NoneType)
print isinstance(None, (NoneType, str, float))
True
True
Although, I would often be inclined to replace isinstance(x, (NoneType, str, float)) with x is None or isinstance(x, (str, float)).
None is the just a value of types.NoneType, it's not a type.
And the error is clear enough:
TypeError: isinstance() arg 2 must be a class, type, or tuple of
classes and types
From the docs:
None is the sole value of types.NoneType. None is frequently used to represent
the absence of a value, as when default arguments are not passed to a
function.
You can use types.NoneType
>>> from types import NoneType
>>> isinstance(None, NoneType)
True
is operator also works fine:
>>> a = None
>>> a is None
True
None is a value(instance) and not a type. As the error message shows, isinstance expects the second argument to be a type.
The type of None is type(None), or Nonetype if you import it (from types import NoneType)
Note: the idiomatic way to do the test is variable is None. Short and descriptive.

Variable with name `None`

I need to have a variable with name None:
class QAbstractPrintDialog(QDialog):
None = int() # QAbstractPrintDialog.PrintDialogOption enum
PrintToFile = int() # QAbstractPrintDialog.PrintDialogOption enum
PrintSelection = int() # QAbstractPrintDialog.PrintDialogOption enum
...
But:
syntax error: cannot assign to None
I need the name to be None. I thought this will work:
QAbstractPrintDialog.None = int() # QAbstractPrintDialog.PrintDialogOption enum
But it didn't. Is there a workaround to not have a syntax error?
Solutions like setattr don't work for me - this code will be parsed to extract classes, functions, arguments, etc.
Python 2.6, 2.7
EDIT:
I am helping a guy to write pseudo-Python modules which contain description of Qt classes. QAbstractPrintDialog is one of the classes and it has enum QAbstractPrintDialog::PrintDialogOption (http://doc.trolltech.com/latest/qabstractprintdialog.html). One of the enums is None. I can easily reference a None attribute via QAbstractPrintDialog.None but i can not set it. int() means the type of the attribute.
See here: http://scummos.blogspot.com/2011/06/kdevelop-python-language-support-plugin.html
In python None is a reserved word and cannot be used as a variable name.
Quoting python documentation:
Changed in version 2.4: Assignments to None are illegal and raise a SyntaxError.
You cannot. None is a Python built-in constant.
To do what you are makes no more sense than:
class = struct
"Assignments to None are illegal and raise a SyntaxError."
--The documentation
Pick another variable name: nil, none, nothing, zilch, not_a_sausage, no_votes, zero, ...
I agree with you that this is a little inconsistent with other built-in constants, viz:
>>> class Foo:
... def __init__(self):
... self.False = True
... self.True = False
... self.None = 'Something'
...
File "<stdin>", line 5
SyntaxError: assignment to None
...but then...
>>> class Foo:
... def __init__(self):
... self.False = True
... self.True = False
...
>>> f = Foo()
>>> f.True
False
>>> f.False
True
>>> f.None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Foo instance has no attribute 'None'
...of course that kind of naming and assignment could only ever lead to trouble!
Call it something distinct like __INSTEADOF_None then strip off all instances of '_INSTEADOF' in a pre-processing step prior to parsing.
It's against the rules to assign to None which has a very special meaning in Python. Choose a different name.
You can try next approach:
>>> class A():pass
>>> a = A()
>>> a.None = 2
SyntaxError: assignment to None
>>> a.__dict__['None'] = 2
>>> a.None
2
>>> dir(a)
['None', '__doc__', '__module__']
But still - idea to use None as object field is really bad.

Iterating class object

It's not a real world program but I would like to know why it can't be done.
I was thinking about numpy.r_ object and tried to do something similar but just making a class and not instantiating it.
a simple code (has some flaws) for integers could be:
class r_:
#classmethod
def __getitem__(clc, sl):
try:
return range(sl)
except TypeError:
sl = sl.start, sl.stop, sl.step
return range(*(i for i in sl if i is not None))
but as I try to do r_[1:10] i receive TypeError: 'type' object is not subscriptable.
Of course the code works with r_.__getitem__(slice(1,10)) but that's not what I want.
Is there something I can do in this case instead of using r_()[1:10]?
The protocol for resolving obj[index] is to look for a __getitem__ method in the type of obj, not to directly look up a method on obj (which would normally fall back to looking up a method on the type if obj didn't have an instance attribute with the name __getitem__).
This can be easily verified.
>>> class Foo(object):
pass
>>> def __getitem__(self, index):
return index
>>> f = Foo()
>>> f.__getitem__ = __getitem__
>>> f[3]
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
f[3]
TypeError: 'Foo' object does not support indexing
>>> Foo.__getitem__ = __getitem__
>>> f[3]
3
I don't know why exactly it works this way, but I would guess that at least part of the reason is exactly to prevent what you're trying to do; it would be surprising if every class that defined __getitem__ so that its instances were indexable accidentally gained the ability to be indexed itself. In the overwhelming majority of cases, code that tries to index a class will be a bug, so if the __getitem__ method happened to be able to return something, it would be bad if that didn't get caught.
Why don't you just call the class something else, and bind an instance of it to the name r_? Then you'd be able to do r_[1:10].
What you are trying to do is like list[1:5] or set[1:5] =) The special __getitem__ method only works on instances.
What one would normally do is just create a single ("singleton") instance of the class:
class r_class(object):
...
r_ = r_class()
Now you can do:
r_[1:5]
You can also use metaclasses, but that may be more than is necessary.
"No, my question was about getitem in the class, not in the instance"
Then you do need metaclasses.
class r_meta(type):
def __getitem__(cls, key):
return range(key)
class r_(object, metaclass=r_meta):
pass
Demo:
>>> r_[5]
range(0, 5)
If you pass in r_[1:5] you will get a slice object. Do help(slice) for more info; you can access values like key.stop if isinstance(key,slice) else key.
Define __getitem__() as a normal method in r_'s metaclass.
The reason for this behavior lies in the way how special methods like __getitem__() are lookup up.
Attributes are looked up first in the objects __dict__, and, if not found there, in the class __dict__. That's why e.g. this works:
>>> class Test1(object):
... x = 'hello'
...
>>> t = Test1()
>>> t.__dict__
{}
>>> t.x
'hello'
Methods that are defined in the class body are stored in the class __dict__:
>>> class Test2(object):
... def foo(self):
... print 'hello'
...
>>> t = Test2()
>>> t.foo()
hello
>>> Test2.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Test2 instance as first argument (got nothing
instead)
So far there's nothing surprising here. When it comes to special methods however, Python's behavior is a little (or very) different:
>>> class Test3(object):
... def __getitem__(self, key):
... return 1
...
>>> t = Test3()
>>> t.__getitem__('a key')
1
>>> Test3['a key']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'type' object is unsubscriptable
The error messages are very different. With Test2, Python complains about an unbound method call, whereas with Test3 it complains about the unsubscriptability.
If you try to invoke a special method - by way of using it's associated operator - on an object, Python doesn't try to find it in the objects __dict__ but goes straight to the __dict__ of the object's class, which, if the object is itself a class, is a metaclass. So that's where you have to define it:
>>> class Test4(object):
... class __metaclass__(type):
... def __getitem__(cls, key):
... return 1
...
>>> Test4['a key']
1
There's no other way. To quote PEP20: There should be one-- and preferably only one --obvious way to do it.

How to create inline objects with properties?

In Javascript it would be:
var newObject = { 'propertyName' : 'propertyValue' };
newObject.propertyName; // returns "propertyValue"
But the same syntax in Python would create a dictionary, and that's not what I want
new_object = {'propertyName': 'propertyValue'}
new_object.propertyName # raises an AttributeError
obj = type('obj', (object,), {'propertyName' : 'propertyValue'})
there are two kinds of type function uses.
Python 3.3 added the SimpleNamespace class for that exact purpose:
>>> from types import SimpleNamespace
>>> obj = SimpleNamespace(propertyName='propertyValue')
>>> obj
namespace(propertyName='propertyValue')
>>> obj.propertyName
'propertyValue'
In addition to the appropriate constructor to build the object, SimpleNamespace defines __repr__ and __eq__ (documented in 3.4) to behave as expected.
Peter's answer
obj = lambda: None
obj.propertyName = 'propertyValue'
I don't know if there's a built-in way to do it, but you can always define a class like this:
class InlineClass(object):
def __init__(self, dict):
self.__dict__ = dict
obj = InlineClass({'propertyName' : 'propertyValue'})
I like Smashery's idea, but Python seems content to let you modify classes on your own:
>>> class Inline(object):
... pass
...
>>> obj = Inline()
>>> obj.test = 1
>>> obj.test
1
>>>
Works just fine in Python 2.5 for me. Note that you do have to do this to a class derived from object - it won't work if you change the line to obj = object.
It is easy in Python to declare a class with an __init__() function that can set up the instance for you, with optional arguments. If you don't specify the arguments you get a blank instance, and if you specify some or all of the arguments you initialize the instance.
I explained it here (my highest-rated answer to date) so I won't retype the explanation. But, if you have questions, ask and I'll answer.
If you just want a generic object whose class doesn't really matter, you can do this:
class Generic(object):
pass
x = Generic()
x.foo = 1
x.bar = 2
x.baz = 3
An obvious extension would be to add an __str__() function that prints something useful.
This trick is nice sometimes when you want a more-convenient dictionary. I find it easier to type x.foo than x["foo"].
SilentGhost had a good answer, but his code actually creates a new object of metaclass type, in other words it creates a class. And classes are objects in Python!
obj = type('obj', (object,), {'propertyName' : 'propertyValue'})
type(obj)
gives
<class 'type'>
To create a new object of a custom or build-in class with dict attributes (aka properties) in one line I'd suggest to just call it:
new_object = type('Foo', (object,), {'name': 'new object'})()
and now
type(new_object)
is
<class '__main__.Foo'>
which means it's an object of class Foo
I hope it helps those who are new to Python.
Another viable option is to use namedtuple:
from collections import namedtuple
message = namedtuple('Message', ['propertyName'], verbose=True)
messages = [
message('propertyValueOne'),
message('propertyValueTwo')
]
class test:
def __setattr__(self,key,value):
return value
myObj = test()
myObj.mykey = 'abc' # set your property and value

Categories

Resources