Архив рубрики: Python

Python проверка на сложность пароля

Например, установлены такие требования к паролю:

  • не меньше 8 символов
  • должна присутствовать хотя бы одна цифра [0-9]
  • должна присутствовать хотя бы одна заглавная буква [A-Z]
  • должна присутствовать хотя бы одна строчная буква [a-z]


Для последовательного перебора символов [a-z] при сравнении, можно использовать такую конструкцию:

>>> for c in range( ord('a'), ord('z')+1 ):
>>> print chr(c),


чтобы получить список [a-z]:
>>> map(chr, range(97, 123))
или
>>> map(chr, range(ord('a'), ord('z')))

Пример реализации. Функция возвращает False, если пароль не удовлетворяет требованиям, или True если ОК:

>>> def lst_seq(v1, v2):
>>>     return map(chr, range(ord(v1), ord(v2)))
>>> def check_psw(psw):
>>>     digit = False
>>>     upper = False
>>>     lower = False
>>>     if len(psw) >= 8:
>>>         for x in psw:
>>>             if x in 
lst_seq('0','9'): 
>>>                 digit = True
>>>             if x in 
lst_seq('A', 'Z'): 
>>>                 upper = True
>>>             if x in 
lst_seq('a', 'z'): 
>>>                 lower = True
>>>     return digit and upper and lower
Теперь варианты от гуру:
для Python 3.3

>>> def check_psw(psw):
>>>     return (len(psw) >= 8 and
>>>         any([ch.isupper() for ch in psw]) and
>>>         any([ch.isdigit() for ch in psw]) and
>>>         any([ch.islower() for ch in psw]))


Вариант с регекспами:

>>> import re
>>> def check_psw(psw):
>>>     return len(psw) >= 8 and

>>>            bool(re.match(«^.*[A-Z]+.*$», psw) and

>>>                 re.match(«^.*[a-z]+.*, psw) and
>>>                 re.match(«^.*[0-9]+.*, psw))

или
>>> import re
>>> def check_psw(psw):
>>>     return bool(re.match(«((?=.*d)(?=.*[a-z])(?=.*[A-Z]).{8})», psw))

или
>>> import re
>>> def check_psw(psw):    
>>>     if len(psw) < 8:
>>>         return False
>>>     for r in ('[a-z]', '[A-Z]', 'd'):
>>>         if re.search(r, psw) is None:
>>>             return False
>>>     return True

Вариант с set для Python 3.3:
>>> import string 
>>> upper  = set(string.ascii_uppercase)
>>> lower  = set(string.ascii_lowercase)
>>> digits = set(string.digits) 
>>> def check_psw(psw):    
>>>     letters = set(psw)
>>>     return bool(len(psw) >= 8 and upper & letters and lower & letters and digits & letters)

Автор: Viktor

Python set методы с наглядными рисунками

Не хватает графики для ясного понимания действий методов set. Хотелось бы как в SQL рисунки пересечений окружностей при работе с join. И вот попал на такой сайт . Выкладываю оттуда картинки.
Union |
>>> s1 = set([1, 2, 3])
>>> s2 = set([3, 4, 5])
>>> print s1.union(s2)

set([1, 2, 3, 4, 5])



Intersection & 
>>> s1 = set([1, 2, 3])
>>> s2 = set([3, 4, 5])
>>> print s1.intersection(s2)

set([3])

Difference 
>>> s1 = set([1, 2, 3])
>>> s2 = set([3, 4, 5])
>>> print s1.difference(s2)

set([1, 2])

Symmetric Difference ^
>>> s1 = set([1, 2, 3])
>>> s2 = set([3, 4, 5])
>>> print s1.symmetric_difference(s2)

set([1, 2, 4, 5])




Автор: Viktor

Использование lambda вместе со списком в Python

Очень наглядный пример использования lambda с методами списков в Python

>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
>>> 
>>> print filter(lambda x: x % 3 == 0, foo)

[18, 9, 24, 12, 27]

>>> 
>>> print map(lambda x: x * 2 + 10, foo)

[14, 46, 28, 54, 44, 58, 26, 34, 64]

>>> 
>>> print reduce(lambda x, y: x + y, foo)

139

>>> digit = [1, 2, 3]
>>> 
>>> print [(lambda x: x * x)(x) for x in digit)]

[1, 4, 9]

или лучше

>>> print [x * x for x in digit]

Еще интересный пример (вырезать в строке лишние дефисы)

>>> line = 'I—like—python'
>>> print '-'.join(filter(lambda x: x != '', line.split('-')))

I-like-python
Объяснение:
>>> line.split('-')
['I', '', '', 'like', '', 'python']
>>> filter(lambda x: x != '', line.split('-')) 
['I', 'like', 'python']

Пример в котором нужно вывести список с НЕ уникальными значениями
Неудачное решение:
>>> lst = [10, 9, 10, 10, 9, 8]
>>> out_lst = []

>>> for i in range(len(lst)):
>>>     x = lst.pop(i)    
>>>     if x in lst:
>>>         out_lst.append(x)
>>>     lst.insert(i, x)
>>> print out_lst
[10, 9, 10, 10, 9]
Лучшее решение:
>>>  print (lambda d:[x for x in d if d.count(x)>1])(lst)
[10, 9, 10, 10, 9]

Автор: Viktor

Функциональный стиль в питоне

Пост чисто философский

Периодическое чтение кусков кода, написанных при обострении хаскеля головного мозга, выработало у меня четкую ассоциацию: функциональный стиль — это нечитаемо. Точнее стиль с множеством map/filter/zip. Вот немного облагороженный пример такого кода (автор считает, что с кодом все ок):

Без подсветки синтаксиса

some_res = ", ".join(
map(str,
filter(None,
map(lambda x: getattr(obj.zip, x, None),
['a', 'b', 'c', 'd']))))

some_res = ", ".join(
map(str,
filter(None,
map(lambda x: getattr(obj.zip, x, None),
['a', 'b', 'c', 'd']))))

Без переписывания в многострочный вариант ориентироваться в нем вообще сложно:

Без подсветки синтаксиса

attrs = ['a', 'b', 'c', 'd']
attr_vals = map(lambda x: getattr(obj.zip, x, None), attrs)
non_none_attrs = filter(None, attr_vals)
some_res = ", ".join(map(str, non_none_attrs))

attrs = ['a', 'b', 'c', 'd']
attr_vals = map(lambda x: getattr(obj.zip, x, None), attrs)
non_none_attrs = filter(None, attr_vals)
some_res = ", ".join(map(str, non_none_attrs))

Этот вариант читается лучше уже потому, что понизилась концентрация логики, и добавились переменные, имена которых служат документацией промежуточным результатам. Но, IMO, это не главные причины.

Первом меня на эту мысль натолкнуло наблюдение за девушкой, которая только начал учить питон и не программировала серьезно до этого. У нее вызывало затруднение определить какие параметры относятся к какой функции даже в достаточно простых выражениях, например:

Без подсветки синтаксиса

x = some_func1(a, b, some_func2(c, d), e)

x = some_func1(a, b, some_func2(c, d), e)

Понятно, что со временем это прошло, но осадок остался — в выражения где много вложенных вызовов и скобок сложно быстро соотнести параметры, функции и удерживать это в голове, пока его анализируешь. Если код не форматирован построчно, как пример выше, то совсем тяжело.

Следующий случай — это функциональный стиль в скале. Его чтение у меня не вызывает того чувства трясины, какое вызывал аналогичный код в python/haskell. Тот же пример на 'скалапитоне' выглядел бы так:

Без подсветки синтаксиса

some_res = ['a', 'b', 'c', 'd'].map(getattr(obj.zip, _, None))
.filter(Non e).map(str).join(",")

some_res = ['a', 'b', 'c', 'd'].map(getattr(obj.zip, _, None))
.filter(None).map(str).join(",")

Если отвлечься от более удобной формы записи лямбды, то он все равно читается гораздо проще. Мне кажется дело в том, что он читается линейно слева направо, а не «вообще изнутри наружу, но местами слева направо», как читается код в питоне.

Это относится скорее не к функциональному стилю, а к процедурный vs ООП, но именно функциональный стиль провоцирует избавление от переменных и написание множества вложенных вызовов функций. Он как лакмусовая бумажка вскрывает плохую масштабируемость читаемости процедурных выражений:

Без подсветки синтаксиса

a(x, b(c(), 1, 4), 'd')
# vs
c().b(1, 4).a(x, 'd')

a(x, b(c(), 1, 4), 'd')
# vs
c().b(1, 4).a(x, 'd')

К сожалению питон чаще всего не позволяет писать сцепленными методами, поскольку бОльщая часть методов возвращает None вместо self (а именно все, которые модифицируют объект на месте), а map/filter — функции, а не методы.

Итого я для себя сменил идею с «функциональный код нечитаем» на «функциональный код, написанный в процедурном стиле, нечитаем».

Ссылки:
          ananthakumaran.in/2010/03/29/scala-underscore-magic.html

Исходники этого и других постов со скриптами лежат тут — github.com/koder-ua. При использовании их, пожалуйста, ссылайтесь на koder-ua.blogspot.com.

Автор: konstantin danilov

Контейнеры внедрения зависимостей для python

Начнем издалека — создание объекта инстанцированием класса плохо совместимо с идеями ООП. Они гласят, что код должен зависеть от интерфейсов, а не от реализаций. До тех пор пока на вход нашему коду приходят готовые объекты — все хорошо. Он будет с готовностью принимать любые типы, реализующие требуемый интерфейс, но как только мы начинаем создавать новые объекты ситуация меняется. Теперь код зависит от конкретного класса, что усложняет следующие задачи:

  • Изменение класса на другой, хоть и реализующий тот же интерфейс. Приходится вручную менять все точки инстанцирования, и, возможно, перекомпилировать код;
  • Выбор конкретного класса на основе внешних условий или точки инстанцирования;
  • Использование уже готового объекта — взятого из пула или какого то конкретного (синглетон);
  • Построение объекта с большим количеством зависимостей — приходиться передавать в точку конструирования все данные для построения множества взаимосвязанных объектов;
  • Не классическая проблема для ICC, но из той-же области:

Без подсветки синтаксиса

class A(object):
def __init__(self, val):
self.val = val

def __add__(self, val):
return A(self.val + val)

class B(A):
pass

print B(1) + 1 # <__main__.A object at 0x18877d0>

class A(object):
def __init__(self, val):
self.val = val

def __add__(self, val):
return A(self.val + val)

class B(A):
pass

print B(1) + 1 # <__main__.A object at 0x18877d0>

А хотелось бы получить экземпляр В.

Все эти проблемы связаны общей причиной — код делает работу, которую он делать не должен — инстанцирование конкретных классов. На самом деле чаще всего нам не нужен фиксированный класс. Нам нужен класс, предоставляющий определенный интерфейс. Нужно отвязаться от явного указания класса и передать его создание стороннему коду. Фактически мы хотим «виртуализовать» инстанцирование.

В самом простом случае можно воспользоваться фабричной функцией(ФФ). Если же мы хотим конфигурировать поведение ФФ, или сохранять состояние между вызовами (синглетон, пул объектов, etc), то логично сделать ФФ методом класса, в экземпляре которого будут храниться настройки. Такой класс может быть синглетоном(если конфигурация глобальная), или передаваться образом по цепочке вызовов во все точки, где нужно инстанцирование. Этот класс как раз и называется Inversion of Control Container (ICC дальше).

Для его использования нужно заменить прямое инстанцирование классов на вызов метода ICC. Параметрами метода будут требуемый интерфейс, и, возможно, контекст вызова и часть параметров для конструктора (последнее применяется редко). ICC возвращает готовый экземпляр. Конкретный класс для инстанцирования и параметры конструктора настраиваются програмно или берутся из конфигурационного файла.

Типичный пример — создание виртуальной машины в libvirt. Основная функция API принимает xml строку, описывающую виртуальную машину. Эта строка чаще всего берется вызывающим кодом из внешнего источника, потому как в большинстве случаев ему не важны подробности конфигурации для работы с VM соответственно и код создания можно унифицировать, а строку с конфигурацией использовать как черный ящик.

ICC также можно рассматривать как шаблон проектирования, объединяющий и унифицирующий другие порождающие шаблоны — ФФ, синглетон, и прочее.

Java и C# имеет различные реализации ICC (java spring, dagger) которые используются очень широко. Для питона же они практически не применяются. Сначала я покажу как написать pythonic ICC, а потом рассмотрю почему он не нужен. Написание своего связанно с тем, что по уже готовые пишутся людьми только что пришедшими с Java/C# и не отличаются питонистичностью.

Итак что можно хотеть от идеального ICC? Во-первых оставить пользовательский код почти без изменений. Во-вторых поддерживать возможность возвращать при инстанцировании целевого класса экземпляры другого класса, или определенный объект или результат вызова некоторой функции.

Итак был такой код:

Без подсветки синтаксиса

class Bee(object):
def __init__(self, x):
pass

class Cee(object):
def __init__(self, x):
pass

assert isinstance(Bee(1), Bee)

class Bee(object):
def __init__(self, x):
pass

class Cee(object):
def __init__(self, x):
pass

assert isinstance(Bee(1), Bee)

Мы хотим иметь возможность не меняя код инстанцирования Bee выбирать что именно будет получаться — экземпляр Bee или Cee. С позиции duck typing классы Bee и Cee реализуют один и тот-же интерфейс и взаимозаменяемы, хоть мы это и не декларируем явным наследованием.

В принципе инстанцирование можно и не менять, но тогда его поведение будет не совсем очевидным. С первого взгляда кажется, что мы инстанцируем обычный класс Bee, а в итоге получаем экземпляр другого класса, который к классу Bee никакого отношения не имеет. Т.е. isinstance(Bee(), Bee) == False. Поэтому немного изменим пример. Bee и Cee будут наследовать общий интерфейс IBee и именно этот интерфейс мы и будем инстанцировать.

Без подсветки синтаксиса

class IBee(IOCInterface):
def __init__(self, x):
pass

class Bee(IBee):
def __init__(self, x):
print "Bee.__init__ called"

class Cee(IBee):
def __init__(self, x):
print "Cee.__init__ called"

IBee.register(Bee)
assert isinstance(IBee(1), Bee)

IBee.register(Cee)
assert isinstance(IBee(1), Cee)

class IBee(IOCInterface):
def __init__(self, x):
pass

class Bee(IBee):
def __init__(self, x):
print "Bee.__init__ called"

class Cee(IBee):
def __init__(self, x):
print "Cee.__init__ called"

IBee.register(Bee)
assert isinstance(IBee(1), Bee)

IBee.register(Cee)
assert isinstance(IBee(1), Cee)

Что бы это работало нужно перехватить конструирование объекта типа IBee и вернуть что-мы-там-хотим. Для этого вспоминаем, что конструирование объекта в python выражается следующим псевдокодом:

Без подсветки синтаксиса

# obj = Cls(x, y) ==>

obj = Cls.__new__(Cls, x, y)
if isinstance(obj, Cls):
Cls.__init__(obj, x, y)

# obj = Cls(x, y) ==>

obj = Cls.__new__(Cls, x, y)
if isinstance(obj, Cls):
Cls.__init__(obj, x, y)

Т.е. Cls.__new__ возвращает пустой экземпляр типа Cls, Cls.__init__ наполняет его реальными данными. Очень похоже на operator new + конструктор в С++. Итак нам нужно перегрузить IBee.__new__ и возвращать из него наш объект.

Без подсветки синтаксиса

ioc = {}

class IOCInterface(object):
def __new__(cls, *args, **kwargs):
return ioc[cls](cls, *args, **kwargs)

@classmethod
def register(cls, impl):
factory = lambda ccls, *args, **kwargs:
super(IOCInterface, ccls).__new__(impl, *args, **kwargs)
cls.register_factory(factory)

@classmethod
def register_instance(cls, obj):
cls.register_factory(lambda *args, **kwargs: obj)

@classmethod
def register_factory(cls, func):
ioc[cls] = func

ioc = {}

class IOCInterface(object):
def __new__(cls, *args, **kwargs):
return ioc[cls](cls, *args, **kwargs)

@classmethod
def register(cls, impl):
factory = lambda ccls, *args, **kwargs:
super(IOCInterface, ccls).__new__(impl, *args, **kwargs)
cls.register_factory(factory)

@classmethod
def register_instance(cls, obj):
cls.register_factory(lambda *args, **kwargs: obj)

@classmethod
def register_factory(cls, func):
ioc[cls] = func

Немного пояснений. Класс IOCInterface будет базовым для всех интерфейсов. Переменная ioc будет хранить текущую конфигурацию — отображение интерфейса на фабричную функцию для этого интерфейса. Для простоты примера мы будем хранить конфигурацию в глобальной переменной. Перегруженный метод __new__ получает инстанцируемый класс первым параметром, а дальше идут параметры конструктора. Он берет зарегистрированную для этого класса фабричную функцию и создает новый объект с ее помощью. IOCInterface.register позволяет зарегистрировать класс для данного интерфейса. IOCInterface.register_instance — зарегистрировать синглетон. Для унификации они создают специальные фабричные функции.

Замечания:

  • Нельзя использовать cls.__new__ как фабричную функцию в IOCInterface.register, так как мы получим вечный цикл. Нужно «проскочить» IOCInterface в иерархии сcls;
  • Для классов с перегруженным __new__ нужно смотреть по ситуации;
  • Есть соблазн просто сохранять класс/синглетон в словарь и потом в __new__

делать что-то вида;

Без подсветки синтаксиса

def __new__(cls, *args, **kwargs):
obj = ioc[cls]
if isinstance(obj, type):
return obj(cls, *args, **kwargs)
elif type(obj, (types.FunctionType, types.LambdaType)):
return obj(cls, *args, **kwargs)
else:
return obj

def __new__(cls, *args, **kwargs):
obj = ioc[cls]
if isinstance(obj, type):
return obj(cls, *args, **kwargs)
elif type(obj, (types.FunctionType, types.LambdaType)):
return obj(cls, *args, **kwargs)
else:
return obj

Делать этого не стоит, хотя бы потому что так мы не сможем зареги

Python, processor affinity или как существенно ускорить некоторые программы, ничего не делая

Всем, кто увидел первую версию поста — цифры были кривые из-за turbo boost

Возьмем простой пример tcp клиента и сервера на python. Сервер создает пул из N потоков и ждет соединений с клиентом. Получив соединение передает его на обработку в пул. На каждом соединении сервер ждет от клиента строку данных и имитирует некую обработку. При получении ‘byen’ сервер завершает обработку клиента.

Читать