Como separar a platéia em 2 grupos
± do mesmo tamanho?
Conte 1 2 1 2 ... para cada pessoa e cada um estará num grupo
Conte 1 2 1 2 ... para cada pessoa e cada um estará num grupo
Mas se quisermos voltar no próximo meetup e ainda ter 2 grupos razoavelmente iguais (em tamanho)?
Como separar a platéia em 2 grupos ± do mesmo tamanho, tal que nos próximos meetups eu consiga saber qual grupo estava, e novas pessoas também possam entrar, mantendo os tamanhos dos grupos equilibrados?
Como separar a platéia em 2 grupos ± do mesmo tamanho, tal que nos próximos meetups eu consiga saber qual grupo estava, e novas pessoas também possam entrar?
Requisito 1
Determinismo
Dado uma pessoa, o número dela será sempre o mesmo
Determine o grupo a partir da data de aniversário da pessoa
Dia do aniversario:
Par → Grupo 0
Impar → Grupo 1
Determine o grupo a partir da data de aniversário da pessoa
1º Algarismo do Mes da pessoa
0 → Grupo 0
1 → Grupo 1
Jan 01 , Ago 08, Maio 05 → 0
Outubro 10 , Dezembro 12 → 1
Distribuição de Nascimentos nos meses: Uniforme
Distribuição de Nascimentos nos dias: Uniforme
Idéia 2
Idéia 3
Idéia 2
Idéia 3
Como separar a platéia em 2 grupos ± do mesmo tamanho, tal que nos próximos meetups eu consiga saber qual grupo estava, e novas pessoas também possam entrar?
Requisito 2
Uniformidade
A função espalha de forma uniforme as entradas nas saídas
Distribuição Uniforme
A função espalha de forma uniforme as entradas nas saídas
Distribuição Uniforme
A saída deve ter ter que estar dentro de uma faixa
=
A saída tem que ter número fixo de bits
>>> hash(10)
10
>>> hash(2**100)
68719476736
>>> hash("")
0
>>> hash("Ola")
3275334880683988321
>>> hash("Olá")
-3830807016388316699
>>> hash("Ola mundo")
7184885651759528628
>>> hash("Ola mundo! Como esta")
-4748936365567857139
>>> hash("Ola mundo! Como esta?")
-2371297093152996703
Hashmap
>>> l = [12, 99, 37]
>>> l[0]
12
>>> l[1]
99
>>> l[2]
37
>>> l[-1]
37
>>> l[0:1]
[12]
>>> l[0:2]
[12, 99]
>>> l[0] = 'string'
>>> l
['string', 99, 37]
>>> del l[2]
>>> l
['string', 99]
dict()
dict()
Mapeia númeos e strings para algum objeto
Nome para Hashtables no Python!
>>> dicionario_vazio = dict()
>>> dicionario_vazio = {}
>>> d = { 1:1, 2:4, 3:9 }
>>> d
{1: 1, 2: 4, 3: 9}
>>> d.keys()
[1, 2, 3]
>>> d.values()
[1, 4, 9]
>>> d.items()
[(1, 1), (2, 4), (3, 9)]
>>> d[2]
4
>>> d[8]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 8
>>> d[10] = 100
>>> d
{1: 1, 2: 4, 3: 9, 10: 100}
>>> a = { 1:10, "python": "de mais", 100: "Cem", "Zero": 0}
>>> a
{'python': 'de mais', 1: 10, 'Zero': 0, 100: 'Cem'}
>>> a['python']
'de mais'
>>> a[100]
'Cem'
>>> a['python'] = "D+"
>>> del a[1]
>>> a
{'python': 'D+', 'Zero': 0, 100: 'Cem'}
>>> a.keys()
['python', 'Zero', 100]
>>> a.values()
['D+', 0, 'Cem']
object()
>>> class ClassName(object):
... def __init__(self, arg):
... self.arg = arg
... def __del__(self):
... print "good bye"
... def method_name(self):
... pass
... def method_with_arg(self, arg1, arg2):
... print arg1, arg2
...
>>> o = ClassName(42)
>>> print o.arg
42
>>> o.method_with_arg("Hi", "There")
Hi There
>>> del o
good bye
cpython/Include/object.h:77-116
typedef struct _object {
long int ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
typedef struct {
long int ob_refcnt;
struct _typeobject *ob_type;
long int ob_size;
/* Number of items in variable part */
} PyVarObject;
cpython/Include/typestruct.h
typedef struct _typeobject {
PyObject_VAR_HEAD
char *tp_name; /* For printing, in format "<module>.<name>" */
int tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
long tp_flags;
char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
long tp_weaklistoffset;
/* Added in release 2.2 */
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
long tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
} PyTypeObject;
variável string que aponta pra um objeto
Font: https://www.safaribooksonline.com/library/view/learning-python-5th/9781449355722/ch06s02.html
dictionaries
{
var1: obj1,
var2: obj2,
func1: obj3,
module1: obj4
}
{
var1: obj1,
var2: obj2,
func1: obj3,
module1: {
var_intern1: objn,
(...)
}
}
Garbage Collector
A = object()
if True:
B = object()
del A
function()
print "END"
Garbage Collector
A = object()
if True:
B = object()
# B disposable
del A # A disposable
function()
print "END"
typedef struct _object {
long int ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
>>> class ClassName(object):
... def __init__(self, arg):
... self.arg = arg
... def __del__(self):
... print "good bye", self.arg
...
>>> o = ClassName(42)
>>> del o
good bye 42
>>> if True:
... n = ClassName("Jim")
...
good bye Jim
Immutable: may be reused
Mutable: Always different instances
>>> a=1
>>> b=1
>>> a is b
True
>>> a=[]
>>> b=[]
>>> a is b
False # a is not b
>>> c = d = []
>>> c is d
True
callable(object)
>>> callable(None)
False
>>> callable(10)
False
>>> callable(object)
True
>>> callable(pow)
True
/* Test whether an object can be called */
int
PyCallable_Check(PyObject *x)
{
if (x == NULL)
return 0;
if (PyInstance_Check(x)) {
PyObject *call = PyObject_GetAttrString(x, "__call__");
if (call == NULL) {
PyErr_Clear();
return 0;
}
/* Could test recursively but don't, for fear of endless
recursion if some joker sets self.__call__ = self */
Py_DECREF(call);
return 1;
}
else {
return x->ob_type->tp_call != NULL;
}
}
cpython/Objects/object.c:1655
def callable(obj):
return obj and hasattr(obj, '__call__')
Immutable
__hash__()
__eq__() or __cmp__()
object.__hash__ == id
__iter__() or __getitem__()
iter(obj)
next(iter)
StopIteration
__get__()
__set__()
__delete__()
property([fget[, fset[, fdel[, doc]]]])
class C(object):
def __init__(self):
self._x = None
def getx(self):
print "get x"
return self._x
def setx(self, value):
print "set x", value
self._x = value
def delx(self):
print "del x"
del self._x
x = property(getx, setx, delx,
"I'm the 'x' property.")
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
print "get x"
return self._x
@x.setter
def x(self, value):
print "set x", value
self._x = value
@x.deleter
def x(self):
print "del x"
del self._x
>>> c = C()
>>> c.x
get x
>>> c.x = 10
set x 10
>>> c.x
get x
10
>>> del c.x
del x
>>> c.x
get x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 9, in x
AttributeError: 'C' object has no attribute '_x'
>>> c.x = 20
set x 20
>>> c.x
get x
20
Objects that references other objects
__getitem__()
__len__()
A container
lookups use arbitrary immutable keys rather than integers
A container
Arquivos
Bytes-like object
etc
Sequences
Sets
Mappings
Callable
__somename__
_ _ duplos underscores _ _