How to test whether x is a member of a universal set? - python

I have a list L, and x in L evaluates to True if x is a member of L. What can I use instead of L in order x in smth will evaluate to True independently on the value of x?
So, I need something, what contains all objects, including itself, because x can also be this "smth".

class Universe:
def __contains__(_,x): return True

You can inherit from the built-in list class and redefine the __contains__ method that is called when you do tests like item in list:
>>> class my_list(list):
def __contains__(self, item):
return True
>>> L = my_list()
>>> L
[]
>>> x = 2
>>> x
2
>>> x in L
True

Theorem: There is no universal set.
Proof. Let X be a set such that X = {\empty, x} where x is every possible element in the domain. The question arises, is X \in X? Most sets are not defined that way, so let us define a new set Y. Y = {A \in X; A \notin A} i.e. Y is the set of all sets not belonging to themselves.
Now, does Y \in Y? Well, we have defined Y as all sets not belonging to themselves, so Y cannot exist in Y, which contradicts our assumption.
So now assume Y is not in Y. Now A definitely contains Y, as Y is not in itself, but the definition of Y is such that if we define Y to be in Y, we contradict our own definition.
Thus, there is no set of all sets. This is known as Russell's Paradox.
So, why programmatically try to create an object that violates a result proved and tested by set theorists far more intelligent than I am? If that was my interview, this would be my answer and if they insisted it was possible, I'd suggest explaining what the problem domain is, since conceptually Russell has fundamentally proved it is impossible.
If you want a user-friendly problem usually posed for people studying introductory set theory, try the Barber Paradox.
Edit: Python lets you implement an object that contains itself. See this:
class Universal(object):
def __init__(self):
self.contents = []
def add(self, x):
self.contents.append(x)
def remove(self, x):
self.contents.remove(x)
def __contains__(self, x):
return ( x in self.contents )
However, this is not a strict set theoretic object, since the contents actually contains a reference to the parent object. If you require that objects be distinct as per the proof above, this cannot happen.

Related

Simentenoulsy pass by value and pass by reference in python?

Premise:
Suppose I have a variable x and two function f(x) and g(x)
such that when f(x) has the ability to change the value of x (maybe it wants to keep track on how many times f(x) has been called) and g(x) doesn't want to change the value of x at any cost.
Now if i was choose x as an integer, I can accomplish g(x) and if x is a list, I can accomplish f(x).
Question:
But what if I want to accomplish both of them in the same program?
What should I do then?.
If its not possible, then doesn't this severely handicap python wrt other languages.
Note:
Basically my question is motivated by finding the drawbacks of not having pointers in python as in other language like C++, the above task can easily be implemented by choosing the *x instead of x.
If all you need to do is change the value of a variable that you pass to f, you can simply return the new value:
def f(x):
return x + 1
x = 30
x = f(x)
# x is now 31
If there is already another value you need to return from f, you can return a tuple and unpack the return value to multiple variables:
def f(x):
return 46, x + 1
x = 30
y, x = f(x)
# x is now 31
In C++, the use of pointers that you bring up compensates for the fact that it's relatively difficult to return multiple values from a function. In Python, while we're still technically returning one value, it's much easier to create tuples and unpack them.
You could make your own class:
`class some_class():
self._value = 0
self._access_counter = 0
def update_value(self):
<your code here>
def get_value_by_ref(self):
self._access_counter += 1
return self._value
`

Argument passing by reference to a class in python (รก la C++), to modify it with the class methods

In this case, I want that the program print "X = changed"
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
self.var = 'changed'
X = 'unchanged'
V = Clase(X)
V.set_var()
print "X = ",X
All values are objects and are passed by reference in Python, and assignment changes the reference.
def myfunc(y):
y = 13
x = 42 # x now points at the integer object, 42
myfunc(y) # inside myfunc, y initially points to 42,
# but myfunc changes its y to point to a
# different object, 13
print(x) # prints 42, since changing y inside myfunc
# does not change any other variable
It's important to note here that there are no "simple types" as there are in other languages. In Python, integers are objects. Floats are objects. Bools are objects. And assignment is always changing a pointer to refer to a different object, whatever the type of that object.
Thus, it's not possible to "assign through" a reference and change someone else's variable. You can, however, simulate this by passing a mutable container (e.g. a list or a dictionary) and changing the contents of the container, as others have shown.
This kind of mutation of arguments through pointers is common in C/C++ and is generally used to work around the fact that a function can only have a single return value. Python will happily create tuples for you in the return statement and unpack them to multiple variables on the other side, making it easy to return multiple values, so this isn't an issue. Just return all the values you want to return. Here is a trivial example:
def myfunc(x, y, z):
return x * 2, y + 5, z - 3
On the other side:
a, b, c = myFunc(4, 5, 6)
In practice, then, there is rarely any reason to need to do what you're trying to do in Python.
In python list and dict types are global and are passed around by reference. So if you change the type of your variable X to one of those you will get the desired results.
[EDIT: Added use case that op needed]
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
self.var.test = 'changed'
class ComplicatedClass():
def __init__(self, test):
self.test = test
X = ComplicatedClass('unchanged')
print('Before:', X.test)
V = Clase(X)
V.set_var()
print("After:",X.test)
>>> Before: unchanged
>>> After: changed
strings are immutable so you could not change X in this way
... an alternative might be reassigning X in the global space... this obviously will fail in many many senarios (ie it is not a global)
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
globals()[self.var] = 'changed'
X = 'unchanged'
V = Clase('X')
V.set_var()
print "X = ",X
the other alternative is to use a mutable data type as suggested by Ashwin
or the best option is that this is probably not a good idea and you should likely not do it...

Default parameter value for objects

Python provides a way to set a default value for function parameters. An example is:
def f(x=3):
print(x)
This is for a primitive type, lets try with objects:
def f(x=list()):
print(id(x))
f()
44289920
f()
44289920
Same object! I was surprised of this being used to the C/C++ way. Done with that, I now understand the default value is not build at invoking time but at definition time.
So I came to a solution:
def f(x=list()):
if len(x) == 0:
x = list()
print(id(x))
Solved! But at what price: In my opinion this doesn't seem to be a very clean solution.
This solution rely in the use of len(x) == 0 as a way to identify the default value which is Ok for my function but not for others so the solution can be generalized as:
def f(x=None):
if x is None:
x = list()
This can be shortened to:
def f(x=None):
x = x or list() # a bit shorter version
My question is, is there any shorter or better way to solve this problem? Will it ever be?
I still prefer the is None approach, but here is a new option to think about: If is defined only the type, you create a new instance of it.
def f(x=list):
if isinstance(x, type): x = x()
print(id(x))

Python - is there a way to implement __getitem__ for multidimension array?

I would like use something like that:
class Board():
...
def __getitem__(self, y, x):
return self.board[y][x]
but unfortunatelly, when I call:
board[x][y]
I get:
TypeError: __getitem__() takes exactly 3 arguments (2 given)
When you do board[x][y] you will cause two calls to __getitem__ because you are doing two separate accesses: [x] is one and [y] is another. There's no way to handle this directly in __getitem__; you'd have to have board[x] return some kind of sub-object that you could use [y] on to get the individual item. What you probably want is to have __getitem__ accept a tuple:
def __getitem__(self, tup):
y, x = tup
return self.board[y][x]
Then do:
board[x, y]
(Note that you have the order of x and y switched between __getitem__ and board[x][y] --- is that intentional?)
You might want to consider using this syntax:
board[(x, y)]
It's less pretty, but it allows you to have multidimensional arrays simply. Any number of dimensions in fact:
board[(1,6,34,2,6)]
By making board a defaultdict you can even have sparse dictionaries:
board[(1,6,34,2,6)]
>>> from collections import defaultdict
>>> board = defaultdict(lambda: 0)
>>> board[(1,6,8)] = 7
>>> board[(1,6,8)]
7
>>> board[(5,6,3)]
0
If you want something more advanced than that you probably want NumPy.
board[x][y] means board.__getitem__(x).__getitem__(y), so Board.__getitem__ has to return some kind of view that also supports __getitem__ and remembers x. This is a bit of work, but for some use cases (anything involving passing that view around) it's very convenient.
Another option is board[x, y], which means board.__getitem__((x, y)). Note that this passes a tuple to __getitem__, which you'll have to unpack manually (there is syntactic sugar for doing this in 2.x, but it's a bit obscure and also gone in 3.x, so you may want to avoid it in the interest of future porting work).
Just do:
class Board():
def __getitem__(self, x):
return self.board[x]
because when you call b[x][y] it actually calls __getitem__() twice, as showed below:
import numpy as np
b = Board()
b.board = np.random.random((3,3,3))
print (b[2][0]==(b[2])[0]).all()
#True
But the best would be to subclass np.ndarray, so that you don't have to re-implement this method:
class Board(np.ndarray):
pass
Say b is the class object b = Board(). When you are looking for B[0][0] __getitem__ won't normally work. Instead what we can do is set b's data equal to a new variable.
boardData = b.data
print(boardData[0][0])

Returning an lvalue from a function in python

[Sorry, I'm new in Python. Although it seems to be a very basic question, I did my share of due diligence before asking this audience, trying to avoid really stupid questions].
I'm trying to figure out the correct idiom for returning an l-value from a function. Assume I've a container of 64 objects, and I want to be able to return a reference to these objects.
class ChessBoard:
def __init__(self):
self.squares = [None for x in range(64)]
square( row, col ):
return self.squares(row*8+col) <---- I'd like this to be l-value
Then, from outside the class I want to:
board = ChessBoard()
board.square(0,0) = Piece( Shapes.ROOK, Colors.White ) <-- I'm getting an error here
board.square(0,1) = Piece( Shapes.BISHOP, Colors.White )
... etc.
So, I would like the function 'at' to return a lvalue (Something like a reference in C++), but I can't find anything resembling a reference or a pointer in the language. If I stored a list in each square containing one Piece, it is possible I could do something like: board.square(0,0)[0] = Piece - but it seems crazy (or maybe not - as I said, I'm new to the language).
How would you approach this data structure?
In Python, everything is a reference. The only problem is that None is immutable, so you can't use the returned reference to change the value.
You also can't override the assignment operator, so you won't get this particular kind of behaviour. However, a good and very flexible solution would be to override the __setitem__ and __getitem__ methods to implement the subscription operator ([]) for the class:
class ChessBoard(object):
def __init__(self):
self.squares = [None] * 64
def __setitem__(self, key, value):
row, col = key
self.squares[row*8 + col] = value
def __getitem__(self, key):
row, col = key
return self.squares[row*8 + col]
Usage:
>>> c = ChessBoard()
>>> c[1,2] = 5
>>> c[1,2]
5
You can try something like this, at the cost of having to put bogus [:] indexers around:
class Board:
def __init__(self):
self.squares=[None for x in range(64)]
def square(self, row, col):
squares=self.squares
class Prox:
def __getitem__(self, i):
return squares[row*8+col]
def __setitem__(self, i, v):
squares[row*8+col]=v
return Prox()
Then you can do
b=Board()
b.square(2,3)[:]=Piece('Knight')
if b.square(x,y)[:] == Piece('King') ...
And so on. It doesn't actually matter what you put in the []s, it just has to be something.
(Got the idea from the Proxies Perl6 uses to do this)
As Niklas points out, you can't return an l-value.
However, in addition to overriding subscription, you can also use properties (an application of descriptors: http://docs.python.org/howto/descriptor.html) to create an object attribute, which when read from, or assigned to, runs code.
(Not answering your question in the title, but your "How would you approach this data structure?" question:) A more pythonic solution for your data structure would be using a list of lists:
# define a function that generates an empty chess board
make_chess_board = lambda : [[None for x in xrange(8)] for y in xrange(8)]
# grab an instance
b = make_chess_board()
# play the game!
b[0][0] = Piece(Shapes.ROOK, Colors.White)
b[0][1] = Piece(Shapes.BISHOP, Colors.White)
# Or use tuples:
b[0][0] = (Shapes.ROOK, Colors.White)
b[0][1] = (Shapes.BISHOP, Colors.White)

Categories