LoginSignup
404

More than 1 year has passed since last update.

朝飯前に学べる!便利なPythonのヒント100選【後編】

Last updated at Posted at 2021-08-02

本記事は、Fatos Morina氏による「100 Helpful Python Tips You Can Learn Before Finishing Your Morning Coffee」(2021年5月10日公開)の和訳を、著者の許可を得て掲載しているものです。

朝飯前に学べる!便利なPythonのヒント100選【後編】


Photo by Jexo on Unsplash

はじめに

Pythonは、主にそのシンプルさと習得のしやすさから、最近では非常に人気があります。

データサイエンスや機械学習、ウェブ開発、スクリプト記述、自動化など、幅広い分野で利用することができます。

この記事はかなり長いので、すぐ始めましょう。

50. filter()は新しいオブジェクトを返す

my_list = [1, 2, 3, 4]
odd = filter(lambda x: x % 2 == 1, my_list)
print(list(odd)) # [1, 3]
print(my_list) # [1, 2, 3, 4]

51. map()は新しいオブジェクトを返す

my_list = [1, 2, 3, 4]
squared = map(lambda x: x ** 2, my_list)
print(list(squared)) # [1, 4, 9, 16]
print(my_list) # [1, 2, 3, 4]

52. range()にはあまり知られていないステップパラメータがある

for number in range(1, 10, 3):
print(number, end=" ")
# 1 4 7

53. range()はデフォルトで0から始まる

そのため、0を含める必要は全くありません。

def range_with_zero(number):
    for i in range(0, number):
        print(i, end=' ')
def range_with_no_zero(number):
    for i in range(number):
        print(i, end=' ')

range_with_zero(3) # 0 1 2
range_with_no_zero(3) # 0 1 2

54. 長さを0と比較する必要はない

長さが0より大きい場合、デフォルトでTrueなので、0と比較する必要はありません。

def get_element_with_comparison(my_list):
    if len(my_list) > 0:
        return my_list[0]
def get_first_element(my_list):
    if len(my_list):
        return my_list[0]

elements = [1, 2, 3, 4]
first_result = get_element_with_comparison(elements)
second_result = get_element_with_comparison(elements)

print(first_result == second_result) # True

55. 同じスコープで同じメソッドを複数回定義できる

ただし、前のものを上書きするため、最後のものだけが呼び出されます。

def get_address():
    return "First address"
def get_address():
    return "Second address"
def get_address():
    return "Third address"

print(get_address()) # Third address

56. 指定スコープ外のプライベートプロパティにもアクセスできる

class Engineer:
    def __init__(self, name):
        self.name = name
        self.__starting_salary = 62000

dain = Engineer('Dain')
print(dain._Engineer__starting_salary) # 62000

57. オブジェクトのメモリ使用量を調べる

import sys
print(sys.getsizeof("bitcoin")) # 56

58. パラメータを何個でも指定して呼び出せるメソッドを定義する

def get_sum(*arguments):
    result = 0
    for i in arguments:
        result += i
    return result

print(get_sum(1, 2, 3)) # 6
print(get_sum(1, 2, 3, 4, 5)) # 15
print(get_sum(1, 2, 3, 4, 5, 6, 7)) # 28

59. super()または親クラス名を使用して、親クラスのイニシャライザを呼び出す

super()を使用して、親クラスのイニシャライザを呼び出すことができます。

class Parent:
    def __init__(self, city, address):
        self.city = city
        self.address = address
class Child(Parent):
    def __init__(self, city, address, university):
        super().__init__(city, address)
        self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')
print(child.university) # ETH Zürich

親クラス名を使用して、親クラスを呼び出します。

class Parent:
    def __init__(self, city, address):
        self.city = city
        self.address = address
class Child(Parent):
    def __init__(self, city, address, university):
        Parent.__init__(self, city, address)
        self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')
print(child.university) # ETH Zürich

なお、__init__()super()を使用した親のイニシャライザの呼び出しは、子クラスのイニシャライザ内部だけで使用できます。

60. 自クラスで「+」演算子を再定義する

2つの整数型で「+」演算子を使用すると、その和を取得します。

2つの文字列型で使用すると、それらをマージします。

print(10 + 1) # Adding two integers using '+'
print('first' + 'second') # Merging two strings '+'

これが演算子のオーバーロードです。

自クラスでも使用できます。

class Expenses:
    def __init__(self, rent, groceries):
        self.rent = rent
        self.groceries = groceries
    def __add__(self, other):
        return Expenses(self.rent + other.rent, self.groceries + other.groceries)

april_expenses = Expenses(1000, 200)
may_expenses = Expenses(1000, 300)

total_expenses = april_expenses + may_expenses
print(total_expenses.rent) # 2000
print(total_expenses.groceries) # 500

61. 自クラスで「<」演算子および「==」演算子を再定義する

自分で定義できる演算子のオーバーロードの例です。

class Game:
    def __init__(self, score):
        self.score = score
    def __lt__(self, other):
        return self.score < other.score

first = Game(1)
second = Game(2)

print(first < second) # True

先の2つと同じように、自分のニーズに基づいて、__eq__()関数を上書きできます。

class Journey:
    def __init__(self, location, destination, duration):
        self.location = location
        self.destination = destination
        self.duration = duration
    def __eq__(self, other):
        return ((self.location == other.location) and
                (self.destination == other.destination) and
                (self.duration == other.duration))

first = Journey('Location A', 'Destination A', '30min')
second = Journey('Location B', 'Destination B', '30min')

print(first == second)

次も同様に定義することもできます。

  • __sub__() 「-」
  • __mul__() 「*」
  • __truediv__() 「/」
  • __ne__() 「!=」
  • __ge__() 「>=」
  • __gt__() 「>」

62. クラスのオブジェクトのカスタム印刷可能なバージョンを定義する

class Rectangle:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __repr__(self):
        return repr('Rectangle with area=' + str(self.a * self.b))

print(Rectangle(3, 4)) # 'Rectangle with area=12'

63. 文字列の文字の大文字と小文字を入れ替える

string = "This is just a sentence."
result = string.swapcase()
print(result) # tHIS IS JUST A SENTENCE.

64. 文字列のすべての文字が空白か調べる

string = " "
result = string.isspace()
print(result) # True

65. 文字列のすべての文字がアルファベットまたは数字か調べる

name = "Password"
print(name.isalnum()) # True, because all characters are alphabets
name = "Secure Password "
print(name.isalnum()) # False, because it contains whitespaces
name = "S3cur3P4ssw0rd"
print(name.isalnum()) # True
name = "133"
print(name.isalnum()) # True, because all characters are numbers

66. 文字列のすべての文字がアルファベットか調べる

string = "Name"
print(string.isalpha()) # True
string = "Firstname Lastname"
print(string.isalpha()) # False, because it contains whitespace
string = "P4ssw0rd"
print(string.isalpha()) # False, because it contains numbers

67. 引数に基づいて、右から文字を削除する

string = "This is a sentence with "
# Remove trailing spaces from the right
print(string.rstrip()) # "This is a sentence with "
string = "this here is a sentence.....,,,,aaaaasd"
print(string.rstrip(".,dsa")) # "this here is a sentence"

同じように、引数に基づいて、左から文字を削除することもできます。

string = "ffffffffFirst"
print(string.lstrip("f")) # First

68. 文字列が数値か調べる

string = "seven"
print(string.isdigit()) # False
string = "1337"
print(string.isdigit()) # True
string = "5a"
print(string.isdigit()) # False, because it contains the character 'a'
string = "2**5"
print(string.isdigit()) # False

69. 文字列が漢数字か調べる

# 42673 in Arabic numerals
string = "四二六七三"
print(string.isdigit()) # False
print(string.isnumeric()) # True

70. 文字列のすべての単語が大文字で始まるか調べる

string = "This is a sentence"
print(string.istitle()) # False
string = "10 Python Tips"
print(string.istitle()) # True
string = "How to Print A String in Python"
# False, because of the first characters being lowercase in "to" and "in"
print(string.istitle())
string = "PYTHON"
print(string.istitle()) # False. It's titlelized version is "Python"

71. タプルでも負のインデックスを使用できる

numbers = (1, 2, 3, 4)
print(numbers[-1]) # 4
print(numbers[-4]) # 1

72. タプルにリストとタプルをネストする

mixed_tuple = (("a"*10, 3, 4), ['first', 'second', 'third'])
print(mixed_tuple[1]) # ['first', 'second', 'third']
print(mixed_tuple[0]) # ('aaaaaaaaaa', 3, 4)

73. リストに条件を満たす要素が出現する回数を簡単に数える

names = ["Besim", "Albert", "Besim", "Fisnik", "Meriton"]
print(names.count("Besim")) # 2

74. slice()を使用して、最後のn個の要素を簡単に取得する

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
slicing = slice(-4, None)

# Getting the last 3 elements from the list
print(my_list[slicing]) # [4, 5, 6]

# Getting only the third element starting from the right
print(my_list[-3]) # 4

次のような通常のスライスタスクにもslice()を使用できます。

string = "Data Science"

# start = 1, stop = None (don't stop anywhere), step = 1
# contains 1, 3 and 5 indices
slice_object = slice(5, None)

print(string[slice_object]) # Science

75. タプルに要素が出現する回数を数える

my_tuple = ('a', 1, 'f', 'a', 5, 'a')
print(my_tuple.count('a')) # 3

76. タプルの要素のインデックスを取得する

my_tuple = ('a', 1, 'f', 'a', 5, 'a')
print(my_tuple.index('f')) # 2

77. ジャンプを使用してサブタプルを取得する

my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(my_tuple[::3]) # (1, 4, 7, 10)

78. インデックスから始まるサブタプルを取得する

my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(my_tuple[3:]) # (4, 5, 6, 7, 8, 9, 10)

79. リスト、集合、辞書からすべての要素を削除する

my_list = [1, 2, 3, 4]
my_list.clear()
print(my_list) # []

my_set = {1, 2, 3}
my_set.clear()
print(my_set) # set()

my_dict = {"a": 1, "b": 2}
my_dict.clear()
print(my_dict) # {}

80. 2つの集合を結合する

1つの方法は、union()メソッドを使用して、結合の結果として新しい集合を返します。

first_set = {4, 5, 6}
second_set = {1, 2, 3}
print(first_set.union(second_set)) # {1, 2, 3, 4, 5, 6}

もう1つの方法は、update()メソッドを使用して、2 番目の集合の要素を 1
番目の集合に挿入します。

first_set = {4, 5, 6}
second_set = {1, 2, 3}
first_set.update(second_set)
print(first_set) # {1, 2, 3, 4, 5, 6}

81. print関数の条件

def is_positive(number):
    print("Positive" if number > 0 else "Negative") # Positive
is_positive(-3)

82. 1つのif文で複数条件を指定する

math_points = 51
biology_points = 78
physics_points = 56
history_points = 72

my_conditions = [math_points > 50, biology_points > 50, physics_points > 50, history_points > 50]

if all(my_conditions):
    print("Congratulations! You have passed all of the exams.")
else:
    print("I am sorry, but it seems that you have to repeat at least one exam.")
# Congratulations! You have passed all of the exams.

83. 1つのif文で、複数条件のうち少なくとも1つの条件を満たす

math_points = 51
biology_points = 78
physics_points = 56
history_points = 72

my_conditions = [math_points > 50, biology_points > 50, physics_points > 50, history_points > 50]

if any(my_conditions):
    print("Congratulations! You have passed all of the exams.")
else:
    print("I am sorry, but it seems that you have to repeat at least one exam.")
# Congratulations! You have passed all of the exams.

84. 空でない文字列をTrueと評価する

print(bool("Non empty")) # True
print(bool("")) # False

85. 空でないリスト、タプル、辞書をTrueと評価する

print(bool([])) # False
print(bool(set([]))) # False

print(bool({})) # False
print(bool({"a": 1})) # True

86. Falseと評価する値は、None、False、数値0である

print(bool(False)) # False
print(bool(None)) # False
print(bool(0)) # False

87. 関数で言及するだけでは、グローバル変数の値を変更できない

string = "string"
def do_nothing():
    string = "inside a method"
do_nothing()
print(string) # string

アクセス修飾子 global も使用する必要があります。

string = "string"
def do_nothing():
    global string
    string = "inside a method"
do_nothing()
print(string) # inside a method

88. collectionsのCounterを使用して、文字列またはリストの要素数を数える

from collections import Counter

result = Counter("Banana")
print(result) # Counter({'a': 3, 'n': 2, 'B': 1})

result = Counter([1, 2, 1, 3, 1, 4, 1, 5, 1, 6])
print(result) # Counter({1: 5, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1})

89. Counter を使用して、2つの文字列がアナグラムか調べる

from collections import Counter

def check_if_anagram(first_string, second_string):
    first_string = first_string.lower()
    second_string = second_string.lower()
    return Counter(first_string) == Counter(second_string)

print(check_if_anagram('testinG', 'Testing')) # True
print(check_if_anagram('Here', 'Rehe')) # True
print(check_if_anagram('Know', 'Now')) # False

sorted()を使用して、2つの文字列がアナグラムか調べることもできます。

def check_if_anagram(first_word, second_word):
    first_word = first_word.lower()
    second_word = second_word.lower()
    return sorted(first_word) == sorted(second_word)

print(check_if_anagram("testinG", "Testing")) # True
print(check_if_anagram("Here", "Rehe")) # True
print(check_if_anagram("Know", "Now")) # False

90. itertoolsのcountを使用して、要素数を数える

from itertools import count
my_vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
current_counter = count()
string = "This is just a sentence."
for i in string:
    if i in my_vowels:
        print(f"Current vowel: {i}")
        print(f"Number of vowels found so far: {next(current_counter)}")

これがコンソールに出力される結果です。

Current vowel: i
Number of vowels found so far: 0
Current vowel: i
Number of vowels found so far: 1
Current vowel: u
Number of vowels found so far: 2
Current vowel: a
Number of vowels found so far: 3
Current vowel: e
Number of vowels found so far: 4
Current vowel: e
Number of vowels found so far: 5
Current vowel: e
Number of vowels found so far: 6

91. 頻度に基づいて、文字列またはリストの要素をソートする

collectionsモジュールのcounterは、デフォルトでは、頻度に基づいて要素をソートしません。

from collections import Counter
result = Counter([1, 2, 3, 2, 2, 2, 2])
print(result) # Counter({2: 5, 1: 1, 3: 1})
print(result.most_common()) # [(2, 5), (1, 1), (3, 1)]

92. リストで最も頻度の高い要素を1行で取得する

my_list = ['1', 1, 0, 'a', 'b', 2, 'a', 'c', 'a']
print(max(set(my_list), key=my_list.count)) # a

93. copy()とdeepcopy()の違い

ドキュメントの説明によると

浅いコピーは、新しい複合オブジェクトを構築し、(可能な範囲で)元のオブジェクトへの参照を挿入します。
深いコピーは、新しい複合オブジェクトを構築し、再帰的に、元のオブジェクトにあるオブジェクトのコピーを挿入します。

より包括的な説明はこちら

浅いコピーは、新しいコレクションオブジェクトを構築し、元のオブジェクトにある子オブジェクトへの参照を挿入することです。基本的に、浅いコピーは1レベルの深さしかありません。コピー処理は再帰的に行わないため、子オブジェクト自体のコピーを作成しません。
深いコピーは、コピー処理を再帰的に行います。つまり、新しいコレクションオブジェクトを構築し、元のオブジェクトにある子オブジェクトのコピーを再帰的に挿入します。この方法でオブジェクトをコピーすると、オブジェクトツリー全体をウォークし、元のオブジェクトとそのすべての子オブジェクトの完全に独立したクローンを作成します。

copy()の例です。

first_list = [[1, 2, 3], ['a', 'b', 'c']]
second_list = first_list.copy()
first_list[0][2] = 831

print(first_list) # [[1, 2, 831], ['a', 'b', 'c']]
print(second_list) # [[1, 2, 831], ['a', 'b', 'c']]

deepcopy()の例です。

import copy

first_list = [[1, 2, 3], ['a', 'b', 'c']]
second_list = copy.deepcopy(first_list)
first_list[0][2] = 831

print(first_list) # [[1, 2, 831], ['a', 'b', 'c']]
print(second_list) # [[1, 2, 3], ['a', 'b', 'c']]

94. 辞書で存在しないキーにアクセスしようとした時のエラー発生を防ぐ

通常の辞書を使用していて、存在しないキーにアクセスしようとすると、エラーが発生します。

my_dictonary = {"name": "Name", "surname": "Surname"}
print(my_dictonary["age"])

送出されたエラーです。

KeyError: 'age'

defaultdict()を使用して、このようなエラーを回避できます。

from collections import defaultdict

my_dictonary = defaultdict(str)
my_dictonary['name'] = "Name"
my_dictonary['surname'] = "Surname"

print(my_dictonary["age"])

95. 独自イテレータを構築する

class OddNumbers:
    def __iter__(self):
        self.a = 1
        return self
    def __next__(self):
        x = self.a
        self.a += 2
        return x

odd_numbers_object = OddNumbers()
iterator = iter(odd_numbers_object)

print(next(iterator)) # 1
print(next(iterator)) # 3
print(next(iterator)) # 5

96. リストの重複を1行で削除する

my_set = set([1, 2, 1, 2, 3, 4, 5])
print(list(my_set)) # [1, 2, 3, 4, 5]

97. モジュールの場所を出力する

import torch
print(torch) # <module 'torch' from '/Users/...'

98. not inを使用して、値がリストに含まれていないか調べる

odd_numbers = [1, 3, 5, 7, 9]
even_numbers = []

for i in range(9):
    if i not in odd_numbers:
        even_numbers.append(i)

print(even_numbers) # [0, 2, 4, 6, 8]

99. sort()とsorted()の違い

sort()は、元のリストをソートします。

sorted()は、ソートされた新しいリストを返します。

groceries = ['milk', 'bread', 'tea']

new_groceries = sorted(groceries)
# new_groceries = ['bread', 'milk', 'tea']
print(new_groceries)

# groceries = ['milk', 'bread', 'tea']
print(groceries)

groceries.sort()
# groceries = ['bread', 'milk', 'tea']
print(groceries)

100. uuidモジュールを使用して、一意のIDを生成する

UUIDとは、Universally Unique Identifierの略です。

import uuid

# Generate a UUID from a host ID, sequence number, and the current time
print(uuid.uuid1()) # 308490b6-afe4-11eb-95f7-0c4de9a0c5af

# Generate a random UUID
print(uuid.uuid4()) # 93bc700b-253e-4081-a358-24b60591076a

101. (おまけ)Pythonでは、文字列はプリミティブ型である

Java経験者なら、Javaでは文字列がオブジェクトを参照するため、非プリミティブ型であることを知っているでしょう。

Pythonでは、文字列はプリミティブ型です。


この記事がお役に立てれば幸いです。ハッピーコーディング!

朝飯前に学べる!便利なPythonのヒント100選【前編】」もご覧ください。

翻訳協力

この記事は以下の方々のご協力により公開する事ができました。改めて感謝致します。

Original Author: Fatos Morina (https://www.linkedin.com/in/fatosimorina/)
Original Article: 100 Helpful Python Tips You Can Learn Before Finishing Your Morning Coffee
Thank you for letting us share your knowledge!

選定担当: @gracen
翻訳担当: @gracen
監査担当: -
公開担当: @gracen

こちらもどうぞ
最近見つけたクールなPythonライブラリ6選
Python開発者のためのクールなPythonプロジェクト案10選

ご意見・ご感想をお待ちしております

今回の記事はいかがでしたか?
・こういう記事が読みたい
・こういうところが良かった
・こうした方が良いのではないか
などなど、率直なご意見を募集しております。
頂いたお声は、今後の記事の質向上に役立たせて頂きますので、お気軽に
コメント欄にてご投稿ください。Twitterでもご意見を受け付けております。
皆様のメッセージをお待ちしております。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
404