pikesaku’s blog

個人的なプログラム勉強メモです。記載内容について一切の責任は持ちません。

Pythonの内包表記

リスト

>>> a = [ x**2 for x in range(1,11)]
>>> a
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> 

※rangeの2個目の引数は終了点。range(1,11)1は1〜10

セット

>>> a = { x**2 for x in range(1,11)}
>>> a
{64, 1, 4, 36, 100, 9, 16, 49, 81, 25}
>>> 

ディクショナリ

>>> a = {i+1:i**2 for i in range(1,11)}
>>> a
{2: 1, 3: 4, 4: 9, 5: 16, 6: 25, 7: 36, 8: 49, 9: 64, 10: 81, 11: 100}
>>>

ジェネレータ

>>> a = (i**2 for i in range(1,11))
>>> next(a)
1
>>> next(a)
4
>>> 

2重ループ

>>> v = [[1,2],[3,4],[5,6]]
>>> v
[[1, 2], [3, 4], [5, 6]]
>>> [i for a in v for i in a] 
[1, 2, 3, 4, 5, 6]
>>> 

左のループ(for a in v)が親ループ。ループで書くと以下

>>> v = [[1,2],[3,4],[5,6]]
>>> w = list()
>>> for a in v:
...   for i in a:
...     w.append(i)
... 
>>> w
[1, 2, 3, 4, 5, 6]
>>> 

PythonのオブジェクトID

オブジェクトIDとは?

インタプリタがオブジェクトを管理するID
メモリ上のオブジェクトの場所を示す情報

2つのオブジェクトが同じかは、is で判定可能
id関数で確認できる

>>> a = [1,2]
>>> b = [1,2]
>>> id(a)
4391089224
>>> id(b)
4391101704
>>> a == b
True
>>> a is b
False
>>> 

リストは可変。2つのオブジェクトは別ものとして管理。
イミュータブル(不変)なオブジェクトのstringで値が同じ場合は同一のIDとなる。
メモリ効果がある。

>>> a = 'abc'
>>> b = 'abc'
>>> id(a)
4389672752
>>> id(b)
4389672752
>>> a == b
True
>>> a is b
True
>>>

PythonのNone型

値が存在しないことを表す特別な値

>>> a = ['',None,1,2]
>>> a
['', None, 1, 2]
>>> a[0] is None
False
>>> a[1] is None
True
>>> a[0]
''
>>> if a[0]:
...   print('test')
... 
>>> if a[1]:
...   print('test')
... 
>>> 

NoneはFalseと判定される
is NoneでNoneであるか判定する。

Pythonのディクショナリ操作

定義方法

>>> a = {'a':1,'b':2}
>>> a
{'b': 2, 'a': 1}
>>> a['c'] = 3
>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> 

キーの存在チェック

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> 'a' in a
True
>>> 'd' in a
False
>>>

インデックスアクセス時に存在しない場合にデフォルト値を返す

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> a['d']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'd'
>>> a.get('d')
>>> a.get('d','hoge')
'hoge'
>>> 

getメソッドは引数でデフォルト値を設定できる。引数がない場合は、Noneを返す。

イテレーションアクセス

キーにアクセスする場合

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> for k in a:
...   print(k)
... 
b
a
c
>>> 

値にアクセスする場合

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> for v in a.values():
...   print(v)
... 
2
1
3
>>> 

両方にアクセスする場合

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> for k,v in a.items():
...   print(k,v)
... 
b 2
a 1
c 3
>>>

データの追加と削除

追加

>>> a
{'b': 2, 'a': 1, 'c': 3}
>>> a['d'] = 4
>>> a
{'b': 2, 'a': 1, 'd': 4, 'c': 3}
>>> 

定義時と同じ

削除

>>> a
{'b': 2, 'a': 1, 'd': 4, 'c': 3}
>>> del a['a']
>>> a
{'b': 2, 'd': 4, 'c': 3}
>>> a.pop('b')
2
>>> a
{'d': 4, 'c': 3}
>>> 

delとpopの違いは、popの場合は値を返す点
存在しないキーを指定してアクセスするとKeyErrorが発生する。

popを使うとKeyErrorは発生させないことが可能。

>>> a
{'d': 4, 'c': 3}
>>> del a['a']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'a'
>>> a.pop('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'a'
>>> a.pop('a', 'hoge')
'hoge'
>>> a
{'d': 4, 'c': 3}
>>> 

Pythonのセット操作

要素の追加削除

discardは該当要素がなくても例外発生しない

>>> a = {1,2,3,4,5}
>>> a.add(6)
>>> a
{1, 2, 3, 4, 5, 6}
>>> a.remove(3)
>>> a
{1, 2, 4, 5, 6}
>>> a.remove(7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 7
>>> a
{1, 2, 4, 5, 6}
>>> a.discard(7)
>>> a
{1, 2, 4, 5, 6}
>>> a.discard(1)
>>> a
{2, 4, 5, 6}
>>> 

合併

>>> a = {1,2}
>>> b = {1,3}
>>> c = {1,4}
>>> a | b | c
{1, 2, 3, 4}
>>> 

共通要素の抽出

>>> a
{1, 2}
>>> b
{1, 3}
>>> c
{1, 4}
>>> a & b & c
{1}
>>> 

差の抽出

>>> a
{1, 2}
>>> b
{1, 3}
>>> c
{1, 4}
>>> a - b - c
{2}
>>>

独自要素の抽出

>>> a
{1, 2}
>>> b
{1, 3}
>>> c
{1, 4}
>>> a ^ b
{2, 3}
>>> a ^ b ^ c
{1, 2, 3, 4}
>>> a ^ (b | c)
{2, 3, 4}
>>> 

要素の全てを含んでいるか確認

>>> a
{1, 2}
>>> b
{1, 2, 3}
>>> c
{2, 4}
>>> a <= b
True
>>> a <= c
False
>>> b >= a
True
>>> b >= c
False
>>> 

Pythonのリスト操作

s[i:j:k]

i番目からj番目までの要素をk個毎に取り出す

>>> a = [0,1,2,3,4,5,6,7,8,9]
>>> a[0:9:2]
[0, 2, 4, 6, 8]
>>> a[0::2]
[0, 2, 4, 6, 8]
>>>

s.index(i)

sの要素の中にiと同じものがあった場合に、その最初のインデックスを返す。

>>> a
[1, 1, 1, 2, 2, 2, 3, 3, 3]
>>> a.index(3)
6
>>> a[6]
3
>>> 

s.count(i)

sの要素の中にiと同じものが何個あるか返す

>>> a
[1, 1, 1, 2, 2, 2, 3, 3, 3]
>>> a.count(2)
3
>>>

enumerate関数

リストのインデックスと要素の両方を取り出す

>>> a = ['a','b']
>>> for i,v in enumerate(a):
...   print(i,v)
... 
0 a
1 b
>>>

MailmanとDMARC

MailmanにDMARC機能が追加されたのでメモ
デフォルト設定なら、前バージョンまでの動きと変わらない。


DMARCとは

SPF/DKIMによる送信者認証を利用した認証の仕組み
SPF/DKIMの以下問題を改善する仕組みを持っている。

SPF/DKIMは認証失敗した時の扱いが明確に定義されていいない。
DNSのDMARCレコードで定義

・送信者が認証結果を知ることができない
→レポートを送信する仕組みを実装

https://www.cuenote.jp/library/marketing/dmarc.html
http://ml.cc.tsukuba.ac.jp/pdf/dmarc-with-mlservice-from.pdf
https://sendgrid.kke.co.jp/blog/?p=3137
https://www.iajapan.org/anti_spam/event/2014/conf0214/pdf/sess1/sakuraba.pdf


MailmanがDMARCを問題にする背景

メンバーが投稿(From: member@example.com)
Mailmanがメンバー展開しリレー(Fromヘッダはそのまま)
リレー先でSPF/DKIM認証を実施→Fromが変わっていないため、SPF認証はエラー。DKIMは認証通りそう?

Mailmanは中継するため、送信者認証失敗の原因になってしまう

DMARC情報よりメンバーへの配信時にRejetc/隔離になることがわかれば、配信時にFromヘッダをMLに変更する機能

元メールを添付
Fromを書き換え
の対策があり。


関連パラメタ

関連パラメタ 意味
DEFAULT_DMARC_QUARANTINE_MODERATION_ACTION DMARCポリシーが隔離の場合、Rejectと同じように扱うかYes/No
DEFAULT_DMARC_MODERATION_ACTION 送信元ドメインのDMARCポリシーが、Rejct or 隔離であった場合の動作を定義
0 = Accept
1 = Munge From
2 = Wrap Message
3= Reject
4 = Discard
DEFAULT_DMARC_WRAPPED_MESSAGE_TEXT 添付ファイル送信を選択した場合の、マルチパート区切り文字列に含む文字の指定
DEFAULT_FROM_IS_LIST DMARC_MODERATION_ACTIONがAcceptではないMLへの投稿に対するデフォルトのアクションを設定する。
0: 何もしない
1: FromヘッダをMLアドレスと置き換え
2: FromをMLにしたメールに元メールを添付して送付
REMOVE_DKIM_HEADERS FROM_IS_LISTが1,2の場合にDKIMヘッダを削除する。理由は、Fromヘッダや添付ファイル化した時に、シグニチャが壊れてしまう可能性があるため
Yes/No