A class is more or less a fancy wrapper for a dict of attributes to objects. When you instantiate a class you can assign to its attributes, and those will be stored in foo.__dict__; likewise, you can look in foo.__dict__ for any attributes you have already written.
This means you can do some neat dynamic things like:
class Employee: pass
def foo(self): pass
Employee.foo = foo
as well as assigning to a particular instance. (EDIT: added self parameter)
A class is more or less a fancy wrapper for a dict of attributes to objects. When you instantiate a class you can assign to its attributes, and those will be stored in foo.__dict__; likewise, you can look in foo.__dict__ for any attributes you have already written.
This means you can do some neat dynamic things like:
class Employee: pass
def foo(self): pass
Employee.foo = foo
as well as assigning to a particular instance. (EDIT: added self parameter)
Try with lambda:
john.greet = lambda : print( 'hello world!' )
The you'll be able to do:
john.greet()
EDIT: Thanks Thomas K for the note - this works on Python 3.2 and not for Python2, where print appeared to be statement. But this will work for lambdas, without statements (right? Sorry, I know only python3.2 (: )
What's the usage of empty class in Python - Stack Overflow
Can you create a class with an empty list attribute
oop - Creating an empty object in Python - Stack Overflow
Does there exist empty class in python? - Stack Overflow
Videos
When you create a new class, you are creating a new type. This newly created type may have some properties, or may not. These properties allow to hold data, methods etc.
Empty class that doesn't inherit any base class would be useful as placeholder.
class ServiceWrapper(object):
pass
def sendMessage(svc:ServiceWrapper):
#do something
#pass
On the other hand, empty classes that inherit other classes is a very common pattern. Specially when defining user exceptions.
class Networkerror(RuntimeError):
pass
try:
raise Networkerror()
except Networkerror:
#do something
#pass
Also recently, the python collections.abc allows creating interface like functionalities.
class ServiceWrapper(ABC):
@abstractmethod
def send(self):...
def sendMessage(svc:ServiceWrapper):
svc.send()
#pass
I recently found myself using empty Python classes as unique "tags" for an observer system.
For example, something like this...
from collections import defaultdict
class OnCreate:
pass
class OnModify:
pass
class OnDelete:
pass
class ObserverSystem:
def __init__(self):
self.observers = defaultdict(list)
def register(self, event, callback):
self.observers[event].append(callback)
def notify(self, event, *args, **kwargs):
for callback in self.observers[event]:
callback(*args, **kwargs)
observer = ObserverSystem()
observer.register(OnCreate, lambda entity: print(f"Entity {entity} created"))
observer.register(OnModify, lambda entity: print(f"Entity {entity} modified"))
observer.register(OnDelete, lambda entity: print(f"Entity {entity} deleted"))
observer.notify(OnCreate, 1)
observer.notify(OnModify, 2)
observer.notify(OnDelete, 3)
I guess, I could have used a of numeric value, or even a string as the "tag", but the class is unique, it's hashable so I can use it as dict key, etc. Seems to work well.
I'm trying to create texas holdem with players being class instances with hand as an attribute of type list. When I instantiate a class with no value for hand it says I need instantiate it with a list, and when I try to use self.hand = None it doesn't allow me to append new generated cards to it since it's value type none, what should I do to work around this?
Edit: Now that I'm home I can add my code for people to see
Main Code
from pokerMethods import *
from playerClass import *
def main():
deckNumber = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
deckSuit = ["Spades", "Diamonds", "Clubs", "Hearts"]
cardList = []
playerList = []
p1 = Player("Herp", "Derp")
p2 = Player("Herpy", "Derpy")
createCard(p1, deckNumber, deckSuit, cardList)
createCard(p2, deckNumber, deckSuit, cardList)
print(p1.hand)
print(p2.hand)
main()Class Code:
class Player:
def __init__(self, fname: str, lname: str, hand = [], money = 0):
self.fname = fname
self.lname = lname
self.hand = hand
self.money = money
def addCard(self, newCard):
self.hand.insert(0,newCard)
def removeMoney(self, bet):
self.money -= bet
def addMoney(self, bet):
self.money += betMethod Code
import random
def createCard(player, deckNumber, deckSuit, cardList,):
cardPlayer = deckNumber[random.randint(0, len(deckNumber)-1)] + " " +
deckSuit[random.randint(0, len(deckSuit)-1)]
if cardPlayer not in cardList:
cardList.append(cardPlayer)
player.addCard(cardPlayer)added hand = [] and then did self.hand = hand because when I did just self.hand = [] it gave me the error
Traceback (most recent call last):
File "Pythons Test Shit\Test'.py", line 17, in <module>
main()
File "Pythons Test Shit\Test'.py", line 9, in main
p1 = Player("Herp", "Derp")
TypeError: __init__() missing 1 required positional argument: 'hand'
and with hand = [] in the initializer
Player 1: ['2 Hearts', '1 Clubs']
Player 2: ['2 Hearts', '1 Clubs']
both instances are having their lists edited
edit 2:
re-read the comments and saw u/Binary101010 's comment, sorry for not trying that before doing all my edits and stuff but thank you so much, it worked
Yes, in Python 3.3 SimpleNamespace was added
Unlike object, with SimpleNamespace you can add and remove attributes. If a SimpleNamespace object is initialized with keyword arguments, those are directly added to the underlying namespace.
Example:
import types
x = types.SimpleNamespace()
x.happy = True
print(x.happy) # True
del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'
You can use type to create a new class on the fly and then instantiate it. Like so:
>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>
The arguments to type are: Class name, a tuple of base classes, and the object's dictionary. Which can contain functions (the object's methods) or attributes.
You can actually shorten the first line to
>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)
Because by default type creates new style classes that inherit from object.
type is used in Python for metaprogramming.
But if you just want to create an instance of object. Then, just create an instance of it. Like lejlot suggests.
Creating an instance of a new class like this has an important difference that may be useful.
>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'
Where as:
>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>>
types.SimpleNamespace was introduced with Python 3.3 to serve this exact purpose. The documentation also shows a simple way to implement it yourself in Python, so you can add it to your pre-Python 3.3 setup and use it as if it was there (note that the actual implementation is done in C):
class SimpleNamespace (object):
def __init__ (self, **kwargs):
self.__dict__.update(kwargs)
def __repr__ (self):
keys = sorted(self.__dict__)
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
return "{}({})".format(type(self).__name__, ", ".join(items))
def __eq__ (self, other):
return self.__dict__ == other.__dict__
But of course, if you donโt need its few features, a simple class Empty: pass does just the same.
If you are looking for a place holder object to which you can add arbitrary static members, then the closest I got is an empty lambda function.
obj = lambda: None # Dummy function
obj.foo = 'far'
obj.bar = 'boo'
print obj.foo, obj.bar
# far boo
Remember: obj is not an object of a class, object doesn't mean class instance, because in Python classes and functions are objects at runtime just like class instances
Suppose you want to store some collection of named data. You could use a dict but you like the look of dotted attributes in a class object. Just create the most boring class possible and use python's native attribute assignment to do the trick. It is usually a question of aesthetics.
If you know the attributes ahead of time you can use namedtuples for this kind of functionality.
From the python docs:
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
Since the parentObject member is of the same type as the class itself, I need to declare this as an empty variable of type "self".
No, you do not need to declare anything in Python. You just define things.
And self is not a type, but the conventional name for the first parameter of instance methods, which is set by the language to the object of the method.
Here's an example:
class Tree(object):
def __init__(self, label=None):
self.label = label
self.parent = None
self.children = []
def append(self, node):
self.children.append(node)
node.parent = self
And here's how that could be used:
empty_tree = Tree()
simple_tree = Tree()
simple_tree.append(Tree('hello'))
simple_tree.append(Tree('world'))
In Python, you don't declare variables as having any type. You just assign to them. A single variable can be assigned objects of different types in succession, if you wanted to do so. "self" is not the type but a naming convention used to refer to the current object, like "this" in Java / C++ (except in Python you could call it anything you wanted).