2025-2I プログラミング1 第12回 講義資料

2025年07月17日(木)5・6時限

1 準備

2 プログラミング学習について (再確認)

第01回講義でも話したように、ジュニアレベルのプログラマ(=ソフトウェアエンジニアのタマゴとして就職して困らないレベル)に到達するには 1,000~2,000 時間 の学習 (経験) と言われています。また「超初心者」が「初心者」になるには 約250時間 の学習 (経験) が必要とも言われています。

つまり、毎週の2コマ (90分) の 授業時間だけ の取組み (=90分×30回=45時間) では圧倒的に学習時間が足りません。授業だけでは4年間 (経験) 続けても1,000時間には到達せず😭、その状況で就職しても同僚や後輩とのスキル差に起因して 不安感😱、焦燥感🥵、劣等感🤮、孤独感🥶、自己否定感🤒 に悩まされる日々がつづく可能性があります。もしかして、現段階で既にそのような状況になっていませんか🙁

これは 「プログラミング」に限った話ではありません。毎週の2コマの体育 (音楽) の授業を受けているだけではスポーツ選手 (ミュージシャン) になれないこと、毎週6コマの英語の授業を受けているだけでは「通訳」や「翻訳者」になれないこと、と同じです。

では、どうすればいいのか…🙁

答えは、授業という枠を超えてプログラミングを学ぶこと (親しむこと) です。例えば、日々のスマホゲームや娯楽動画に費やす時間をプログラミング学習に変えてみてください。平日1時間、休日3時間をプログラミングに使えば、週あたり「約10時間」が確保できます。1年間は約52週なので、1年では「520時間の学習時間」となります。

普通の中高校生が 部活動や入試勉強に費やしている時間 を考えれば「平日の1時間・休日の3時間」という時間は、それほど無理な設定ではありません。また、将来的に1日8時間 × 40年間を費やす仕事に関わるスキルと考えれば、十分に投資価値のある行動・時間だと分かると思います。

…とはいえ、授業や塾、部活動のように強制力が働かない環境で「学び」を継続することは簡単ではありません。「学び」に充てる時間を無理なく確保する方法は「プログラミング関係のコンテストやセミナーに参加すること」あるいは「チームとして開発活動すること (=例えば 総合課題実習や高専祭展示に向けた開発活動!!)」です。これらの機会や環境を上手に利用して、自然とプログラミングを学ぶこと (親しむこと) ができるようにして欲しいと思います。それも楽しめないようであれば、ICTエンジニアとして働くことは苦行になると思います。

「どんな活動をすればよいか分からない」「何から学んだらよいのか分からない」「どうやって学んだらよいのか分からない」という場合は、皆さんからアポをとって足を運んでくれれば、いつもでアドバイスします。

3 復習 (リストとnparray)

前々回前回の講義では、NumPy (ナンパイ) の np.arange を使った 繰り返し計算処理 について学びました。基本的かつ様々な場面で利用する処理なので定着させておいてください。

3.1 練習問題

※ 今回の演習の実装例 (解答例) は こちら を参照してください。

3.1.1 問題 1

次の値を np.arange を利用して数値計算せよ。※ 微分積分1の教科書 p.12 の「例1.12」から抜粋。

\[ \sum_{k=1}^{10}(4k-3) \]

3.1.2 問題 2

次の級数の和を np.arange を利用して数値計算せよ (近似計算で可)。※ 微分積分1の教科書 p.28 の [6] から抜粋。

\[ \sum_{n=1}^{\infty}\frac{1}{2^{n-1}} \]

4 辞書 (dict)

Python における 辞書 (=dict, Dictionary) は、他のプログラミング言語では 連想配列ハッシュハッシュテーブル と呼ばれているものです。

辞書は「キー (Key)」と「値 (Value)」の組み合わせを格納する組込み型のデータ構造で「キー (多くの場合は文字列) 」を使って「値 (Value)」を高速に参照 (=取得) できる点に特徴があります。

例えば、辞書は次のように初期化して (初期値を設定して)、その後、キーを使ってそれに対応するを参照することができます。なお、辞書に使用する括弧は [ ] ではなく { } なので注意してください。

下記のプログラムを実行し、その結果を確認してください (元ネタ)

%reset -f

# 辞書の【初期化】 keyとvalueを : で区切って与える
player = {
  'name': '勇者ヨシヒコ', # 各ペアはカンマで区切る
  'level': 3,
  'hp': 120,
  'attack': 16,
  '称号': '正義漢', # key には日本語も利用可能
  'items': ['いざないの剣','たびびとのふく','やくそう'] # リストも格納可能
}

# 辞書の値【参照】[] に key を与えて value を参照
print( player['name'] ) # => 勇者ヨシヒコ'
# print( player[name] )   # => 実行時エラー。name という変数は存在しない

上記の 第15行目 をアンコメントすると (=コメントアウトを解除すると) 実行時エラーになることを確認してください。

player['name'] ではなく player[name] のようにしてしまうと、name という文字列をキーとするのではなく、name という変数を探し、その変数に格納されている値をキーとして事象の値を参照する処理 になってしまいます。プログラムのなかには name という変数は存在しないので、当然ながら NameError が発生します。

もし、print(player[name]) によって、意図する値を出力したいのなら、その文の前に name='name' を記述しておく必要があります。

なお、f文字列の内部で キー (文字列) を使って辞書の値の参照する場合 は、以下のように「シングルクォーテーション」と「ダブルクォーテーション」を使い分けしてください。

print( f"HP = {player['hp']}" ) # => HP = 120

もしくは、次のようにすることも可能です。

print( f'HP = {player["hp"]}' ) # => HP = 120

4.1 演習1 ( 目標時間: 8分)

次のような 期待する出力 が得られるように dict01.py の第13行目以降を書き換えてください。

(期待する出力)

勇者ヨシヒコ (正義漢)
 - Lv : 3
 - HP : 120
 - 持ち物 : いざないの剣, たびびとのふく, やくそう

(ヒント)

4.2 辞書の値 (value) の更新、キーと値のペアの追加

次のプログラムを実行して、その結果を確認してください。また、その実行結果とプログラムを照らし合わせて、辞書型の特性について理解してください。必要に応じてコードを書き換えて、その実行結果がどう変化するかを実証的に確認してください。

%reset -f

# キーとして 'x' と 'y' を持った辞書の値を「整形表示」する関数を定義
def print_point(p):
  assert type(p) is dict  # 辞書型(dict)であることを確認
  print(f"({p['x']:.1f}, {p['y']:.1f})")

p1 = {} # 空の辞書を作成(辞書の初期化)。「p1=dict()」でも同じ処理になる
p1['x'] = 10  # key:'x'  value:10  の追加
p1['y'] = 20

p2 = {'y':100, 'x':50} # キーは順不同で可
p2['y'] = 40 # 書き換え(上書き)

print_point(p1)
print_point(p2)

上記のプログラムの解読を通して、以下のことが分かると思います。

4.2.1 定着確認

4.3 辞書が特定のキーを持つかチェックする方法

次のようにして、辞書が 特定のキーを持っているか を判定することができます。プログラムを実行して、その結果を確認してください。

%reset -f
items = { 
  'やくそう':8,
  'どくけしそう':2,
  'ぬののふく':1
}

for x in ['やくそう', 'きえさりそう'] : # ループ変数 x は「やくそう」→「きえさりそう」
  print(f'勇者ヨシヒコは「{x}」を',end='')
  if x in items.keys() : # 辞書型にキー「x」が含まれるか?
    print(f'{items[x]}個もっている。')
  else :
    print('もっていない。')

4.3.1 定着確認

4.4 演習2 ( 目標時間: 10分)

期待する結果に示すように 辞書が持っているキーと値を全列挙する方法 について、ウェブ検索や生成AIなどを利用して調べて理解し、実際に検証してください (処理の目的が明確なとき、それを自己解決するための演習です) 。

具体的には、次のように初期化された辞書から 期待する結果 を得るようなコードを記述してください。

%reset -f

# この関数を書き換える
def print_dict(d):
  assert type(d) == dict
  print('...')

character_status = {
  'name': 'Hiro',
  'level': 10,
  'hp': 100,
  'mp': 30,
  'attack': 15,
  'defense': 10,
  'experience': 0,
}

print_dict(character_status)

(期待する結果)

name       : Hiro
level      :   10
hp         :  100
mp         :   30
attack     :   15
defense    :   10
experience :    0

ヒント f文字列の書式指定 (左寄せの空白埋め、右寄せの空白埋め) を上手に活用してください。書式指定は第03回講義で既に学習済みです。

%reset -f
num = 123
print(f'...{num:>10}...')
print(f'...{num:<10}...')

4.4.1 定着確認

5 リストの扱いに関する補足① : for構文との組み合わせ

第08回講義で学んだように、for構文を使ってリストの全要素を参照するような処理は、次のように記述することができます。

%reset -f
items = ['やくそう', 'どくけしそう', 'ひのきのぼう', 'たびびとのふく']
# print(len(items)) # => 4
for i in range(len(items)):
  print(items[i])
%reset -f
items = ['やくそう', 'どくけしそう', 'ひのきのぼう', 'たびびとのふく']
for c in items: # このようにスマートに記述可能
  print(c)

上記では、ループ変数 c には数値ではなく、リスト arr の要素 (つまり「やくそう」「どくけしそう」…) が順番に格納されながら繰返し処理されます。

Python では基本的に loop01b.py のような記述が推奨されます。loop01a.pyの記述は非推奨です。

5.1 Enumerate

リストと繰返しを組み合わせる場合、以下のように「その要素は何番目か」もあわせて出力したい場合があります。

1. やくそう
2. どくけしそう
3. ひのきのぼう
4. たびびとのふく

このような場合は enumerate 関数 (イニューマレイト関数) を利用して次のように記述できます。enumerate は 列挙する という意味になります。実際に実行して、その結果について確認してください。

%reset -f
items = ['やくそう', 'どくけしそう', 'ひのきのぼう', 'たびびとのふく']
for i,c in enumerate(items): # ここに注目!
  print(f'{i+1}. {c}')

さらに、enumerate 関数は、第2引数に初期値を設定可能で、以下のように記述することもできます。

%reset -f
items = ['やくそう', 'どくけしそう', 'ひのきのぼう', 'たびびとのふく']
for i,c in enumerate(items,1): # i の初期値を 1 に設定
  print(f'{i}. {c}')

enumerate 関数は、利用頻度が高いので覚えておくようにしてください ( 自分は使う予定がなくても、他人のプログラムを読む場面で出現するので、enumerateの挙動は十分に理解しておいてください )。

5.2 演習3 ( 目標時間: 10分)

下記の「期待する出力」が得られるように、次のプログラムを変更・追記し、その実行結果を確認してください。

%reset -f
codename = ['Coffee Lake Refresh','Comet Lake',
            'Rocket Lake','Alder Lake','Raptor Lake','Meteor Lake']
# ここから先にコードを追加

期待する出力

■ intel デスクトップPC用Coreプロセッサのコードネーム
第09世代 Coffee Lake Refresh
第10世代 Comet Lake
第11世代 Rocket Lake
第12世代 Alder Lake
第13世代 Raptor Lake
第14世代 Meteor Lake

6 リストの扱いに関する補足② : アンパック

第10開講で簡単に触れていますが unpack-01a.pyunpack-01b.py のようにスマートに記述することができます。

どちらのプログラムも同じ出力が得られることを確認してください。

%reset -f
ip_addr = [192,168,110,4]
print(ip_addr[0], ip_addr[1],ip_addr[2],ip_addr[3],sep='.')
%reset -f
ip_addr = [192,168,110,4]
print(*ip_addr,sep='.') # アンパック。リストの先頭の * に注目

Pythonにおける アンパック または アンパッキング とは、リスト内の要素を個々の変数に分割して関数の引数に与える手法を指します。アンパックするためには、変数名の先頭に * を与えます。

7 リストの扱いに関する補足③ : スライス

Pythonのリストでは スライス という操作により、指定の部分範囲を取得することができます。スライスは [] の内部で、コロン : を使って、[開始値:終了値] のように範囲を表現します。

例えば arr[2:6] とした場合、次の図のようにリスト arr の「2番目から5番目 (=6-1番目)までの範囲」の部分取得ができます。また、開始値を省略すると「リストの先頭から」となり、終了値を省略すると「リストの末尾まで」の意味になります。

img

スライスしたものは、関数の引数などに利用可能です。例えば、次のプログラムは、合計 を求める組み込み関数 sum() の引数に「スライスしたリスト」を与えています。実際に実行して、その結果について確認してください。

%reset -f
arr = [10,20,30,40,50,60,70,80]
s1 = sum(arr)
print(f's1 = {s1}') # sum

s2 = sum(arr[:3]) # 0番目から2番目(3番目を含まない)までの合計
s3 = sum(arr[3:]) # 3番目から最後までの合計
s4 = sum(arr[2:6]) # 2番目から5番目までの合計
print(f's2={s2}, s3={s3}, s4={s4}') 

8 文字列に対する1文字参照やスライス処理

「文字列」は「リスト」ではありませんが、「リスト」と同じように [] を使って要素 (=1文字) を参照したり、スライスで部分文字列を取得することができます。半角文字、全角文字、絵文字を含めてPythonでは適切に「1文字」を切り分けることができます。

例えば、変数 item に「やくそう」という文字列が格納されている場合…

…を参照することができます。

ただし、あくまで「リストと同じように操作できる」だけで、文字列はリストではないので name[0]='ど' のような操作はできません (薬草を毒草に変えることはできません)。書き換えようとすると、どのようなエラーになるのか実際にコードを書いて確認してください。

以下は、トランプのカードを「スート (♠♦♥♣) 」と「ランク (A234…JQK) 」の 2文字からなる文字列 として表現し、さらに [] を使って「スート」と「ランク」を個別参照している例です。実際に実行して結果を確認し、プログラムを解読・理解してください。

%reset -f
import random as r
cards = ['♠A', '♠2', '♥3', '♥4','♣Q', '♣K']

print(f'山札は {cards}')

print()
card = r.choice(cards)
print(f'山札から1枚ひいたカードは「{card}」')
print(f'  スートは「{card[0]}」、ランクは「{card[1]}」でした。') 
print()

cards.remove(card)
print(f'よって、現在の山札は {cards}')

また、文字列は、次のようにfor文にも使うことができます。

%reset -f
string = '微分積分1で爆死'
print(' _人人_')
for c in string : # for in (文字列)
  print(f'_) {c} (_')
print(' ^Y^Y^^')

9 GoogleColab.の出力セルのクリア

Jupyter環境 (Google Colab.) における出力セルは IPython.display.clear_output() によって内容をクリア (消去) することができます。

次のプログラムを実行して、その結果について確認してください。

%reset -f
import time
import IPython.display # 要インポート

for i in range(5,0,-1):
  print(f'{i}...')
  time.sleep(1) # Arduino の wait に相当。単位は「秒」
  IPython.display.clear_output() # 出力セルの消去

print('🚀')
for i in range(3):
  time.sleep(0.5)
  print('⚡')

9.1 応用例

自由課題のヒントにしてください。

%reset -f
import time
import random as r
import IPython.display

n=9           # 9回(イニング)までのゲーム委
G = [-1]*n    # スコアの初期化
H = [-1]*n
wait_time = 2 # [Sec]

# チームのスコア #########################
def print_team_score(name,score):
  print(f'{name}|',end='')
  for i in range(n):
    if score[i] != -1:
      print(f'{score[i]:>2}|',end='')
    else :
      print('  |',end='')
  print(f'{sum(score[:t]):>2}|')

# スコアボード全体の出力 #################
def print_score_board():

  IPython.display.clear_output() # 出力をクリア

  print('-+'+'--+'*(n+1))
  print(' |',end='')
  for i in range(1,n+1):
    print(f'{i:>2}|',end='')
  print('計|')
  print('-+'+'--+'*(n+1))

  print_team_score('G',G)
  print_team_score('H',H)

  print('-+'+'--+'*(n+1))

# メイン処理 #############################
for t in range(n):

  # 先攻「G」の攻撃回
  G[t] = r.choices([0,1,2,3],[5,3,1,1])[0]
  print_score_board()
  time.sleep(wait_time)

  # 後攻「H」の攻撃回
  H[t] = r.choices([0,1,2,3],[4,3,2,1])[0]
  print_score_board()
  time.sleep(wait_time)

if sum(H) > sum(G):
  print('😄😄😄😄😄')
else :
  print('😱😱😱😱😱')

10 条件式の工夫

ユーザーから入力された文字列が または いぬ または イヌ のとき、「ワン ! 」という文字列を出力する処理を考えます。

この処理 (条件分岐) を素直に記述すると次のようになります。orOR条件 を表現しています。or第06回講義で既に学習済みです。

%reset -f
animal = input('動物名を入力してください : ')
if animal == '犬' or animal == 'いぬ' or animal == 'イヌ' :
  print('ワン!')
else :
  print('・・・')

これに対して、(初心者において) よくある間違いとして、次の第03行目のように不適切な条件式を記述してしまうことがあります。

%reset -f
animal = input('動物名を入力してください : ')
if animal == '犬' or 'いぬ' or 'イヌ' : # 不適切な条件式
  print('ワン!')
else :
  print('・・・')

上記の条件式 animal == '犬' or 'いぬ' or 'イヌ' では「ネコ」を入力した場合でも「ワン ! 」が出力されてしまいます。実際に実行して結果を確認してみてください。この理由は、if文の 条件式を書く位置 には、単なる「数値」や「文字列」も記述可能で、その場合、特定の値以外では条件が「」として判定されるためです。

実際に確認してみます。以下のプログラムを実行して、その結果を確認してみてください。以下に示す例では、すべての条件が「」として判定され、処理 (print()) が実行されています。

%reset -f
if 'いぬ' :
  print('1')

if 109 :
  print('2')

if -20 :
  print('3')

if 3.14 :
  print('4')

if ['A','B','C'] :
  print('5')

if [0] :
  print('6')

# 次の XXX の部分を自分で思いつく値に変更して実行してみてください。
# if XXXX :
#   print('7')

一方で、条件が「」として判定されるのは、次のように限られた値だけになります。実際に、その実行結果を確認してみてください。

%reset -f
if 0 :
  print('1')

if 0.0 :
  print('2')

if [] :
  print('3')

if None:
  print('4')

if False :
  print('5')

if '' :
  print('6')

以上踏まえ、条件式に animal == '犬' or 'いぬ' or 'イヌ' を使用すると、animal の内容に関係なく、いぬ が「真」となってしまいます。

よって、animal が「犬」「いぬ」「イヌ」のいずれかのときだけ「」とするためには、最初に示したように animal == '犬' or animal == 'いぬ' or animal == 'イヌ' と記述するか、第08回講義 で学んだように次のようにする必要があります。

%reset -f
animal = input('動物名を入力してください : ')
if animal in ['犬','いぬ','イヌ'] : # リスト ['犬','いぬ','イヌ'] に anmial は含まれるか?
  print('ワン!')
else :
  print('・・・')

11 プログラマの心得「前向きな怠惰の思想」

ICTエンジニア (特にプログラマやSE) には「面倒な作業はラクして簡単に瞬殺で済ませようとする「前向きな怠惰」の姿勢や信念」が必要です。これは、言い換えれば「めんどくさいことをしないためならいかなる努力も惜しまない姿勢や信念」が必要とも言えます。

「関数化できる処理を、関数定義しない」、「変数を使わずに、数値リテラルを使用する」、「同じような処理をfor文を利用せずに記述する」といった姿勢では、プログラミングスキルは一向に伸びませんし、コーディングはいつまでも面倒なままで、楽にも楽しくもなりません。

11.1 具体的な事例

一般に、自由課題では「トランプ」を使ったゲームをテーマにプログラミングに取り組む学生が多いです。

例えば、52枚のカードの初期化について、最も愚直な方法は次のようなものです。

%reset -f
# プログラマ的な発想・姿勢に基づかない初期化
cards = ['♠A', '♠2', '♠3', '♠4', '♠5', '♠6', '♠7', '♠8', '♠9', '♠10', '♠J', '♠Q', '♠K',
         '♦A', '♦2', '♦3', '♦4', '♦5', '♦6', '♦7', '♦8', '♦9', '♦10', '♦J', '♦Q', '♦K',
         '♥A', '♥2', '♥3', '♥4', '♥5', '♥6', '♥7', '♥8', '♥9', '♥10', '♥J', '♥Q', '♥K',
         '♣A', '♣2', '♣3', '♣4', '♣5', '♣6', '♣7', '♣8', '♣9', '♣10', '♣J', '♣Q', '♣K']
print(cards)

上記のコードを記述に要する時間は、せいぜい3分程度ですが、この3分の面倒を避けるために プログラムを、考えたり、調べたり、試行錯誤したりすることに1時間、2時間を費やすことができるか が、プログラミング思考になれているか、否かの指標になります。

このような めんどくさいことをしないためならいかなる努力も惜しまない ということができれば、上記 card_init_01.py は、次のように書けることに気付き、その内容の理解に至ると思います。これにより、このカードの初期化に相当するタスクからは 永遠に解放される という恩恵を得ることができます。

%reset -f
# プログラマ的な発想・姿勢に基づく初期化
suit = ['♠','♥','♦','♣']
rank = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
cards = [None]*(len(suit)*len(rank))
t = 0
for s in suit:
  for n in rank :
    cards[t]=f'{s}{n}'
    t+=1
print(f'cards={cards}')

さらに、時間を費やせば、次のようなプログラムにできるというところに到達すると思います。

%reset -f
suit = list('♠♥♦♣')
rank = ['A'] + list(map(str, range(2, 11))) + list('JQK')
cards = [None]*(len(suit)*len(rank))
t = 0
for s in suit:
  for n in rank :
    cards[t]=f'{s}{n}'
    t+=1
print(f'cards={cards}')

さらに、時間を費やせば、次のようなプログラムにできるというところに到達すると思います (ラムダ式mapなどを含んだ下記のコードを理解するためには、数時間~十数時間を必要とします、現時点では以下の詳細について必ずしも理解する必要はありません) 。

itertools.product() 関数は「情報2」の第12回講義 (データベース関連) で学んだ集合演算の「直積」に相当する処理です。

%reset -f
import itertools
suit = list('♠♥♦♣')
rank = ['A'] + list(map(str, range(2, 11))) + list('JQK')
cards = list(map( lambda x: x[0]+x[1],itertools.product(suit,rank)))
print(f'cards={cards}')

11.2 演習4 ( 目標時間: 15分)

次に示すプログラムの Step1 のトランプの初期化を「全52枚」に書き換え、さらに judge() 関数を完成させてください。ここでカードは、ランクが大きいほうが強いものとします (ただし、例外的にキングよりもエースが強いものとします)。

また、ランクが同じ場合は、スペード、ハート、ダイヤ、クローバの順で強いものとします (スートではスペードが最強) 。

%reset -f
import random as r

# 引数で受け取った札束の状態を確認する関数
def print_cards (x) :
  assert type(x) is list
  print(f' ※現在の山札は |',end='')
  print(*x,sep='|',end='') # アンパック
  print(f'| の {len(x)}枚 です。')

# c1 が強い場合は「True」, c2が強い場合は「False」を返す関数
def judge(c1,c2):
  assert type(c1) is str
  assert type(c2) is str
  assert c1 != c2
  return True # 現状では常に True を返す関数になっている

## Step1 ####
print(f'トランプの初期化')
cards = ['♠A', '♠2', '♥10', '♥4','♣Q', '♣K']
print_cards(cards)

## Step2 ####
print()
r.shuffle(cards)
print(f'山札をシャッフルしました。')
print_cards(cards)

## Step3 ####
print()
p1 = cards.pop()
print(f'P1が山札から 1枚ひいたカードは |{p1}| でした。 ',end='')
print(f'このカードのスートは「{p1[0]}」、ランクは「{p1[1:]}」です。')
print_cards(cards)

## Step4 ####
print()
p2 = cards.pop()
print(f'P2が山札から 1枚ひいたカードは |{p2}| でした。 ',end='')
print(f'このカードのスートは「{p2[0]}」、ランクは「{p2[1:]}」です。')
print_cards(cards)

## Step5 ####
print()
print('この勝負、P1の「',end='')
if judge(p1,p2) : # 自作関数 judge の呼び出し
  print('勝ち',end='')
else :
  print('負け',end='')
print('」です。')

(中級者向け) 上記プログラムの Step3 と Step4 は、ほぼ同じ処理といえる。この処理を関数を使ってまとめよ。

ヒント:draw_card という関数で、「山札」と「名前(P1やP2)」を与え、引いたカードを返すような関数

12 ライブラリのインポートに関する補足

自由課題に取り組む際、様々なウェブを参照すると思います。ウェブに掲載されているサンプルプログラムでは from math import sin のように from を含んだ インポートの表記 を見かけると思います。

from を使用する場合と、使用しない場合では、以下のように、ライブラリに含まれる 関数の呼び出し が、若干変わってきます。

%reset -f
# from を使用したimport文
from math import sin,cos
x = sin(0.25)**2 + cos(0.25)**2 # math.は不要
print(x)
%reset -f
# from を使用しないimport文
import math
x = math.sin(0.25)**2 + math.cos(0.25)**2 # math.が必要
print(x)