프로그래밍/Python2014.07.15 00:56

이전까지 다뤄졌던 pingrange Python 예제를 변형해봅니다.

 

코드를 모두 짤 수 없다면, 잘 짜여진 기본 에제를 바탕으로 필요한 내용을 수정/보완하는 것도 중요할 것입니다.

물론 그렇게 하기 위해서는 기존 코드를 잘 이해하는 것이 매우 중요합니다.

 

기존 예제 소스를 이해하기 위해서 이론 정리만 했다면 이번 변형 예제는 기존 예제와 달라진 점을 비교해보고

또한 변형 예제에 대해서는 나름대로.. 친절하게 주석을 달았습니다.

물론 이론적인 부분이 함께 알아두고, 코드를 잘 쪼개서 볼 수 있어야 이해가 쉬울 것입니다.

 

 기존 예제 포스팅은 아래와 같습니다.

 

Python for Networker : Part 2                  Python for Networker : Part 3                    Python for Networker : Part 4 

 

기존 예제는 아래에서 볼 수 있습니다.

[ 예제 링크 ] https://github.com/datacenter/who-moved-my-cli

 

※ 본 내용의 진행은 Nexus 5548 6.0(2)N2(4) 기준입니다.

 

※ Modified Version Code는 다음에서 받을 수 있스니다.

      - https://github.com/NetworkZIGI/Python_for_Network

 


 

 

pingrange.py

import re

from cisco import cli

from argparse import ArgumentParser

def expandrange(rangefunc):

    hosts = []

    octets = rangefunc.split('.')

    for i,octet in enumerate(octets):

        if '-' in octet:

            octetrange = octet.split('-')

            for digit in range(int(octetrange[0]), int(octetrange[1])+1):

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])

                hosts += expandrange(ip)

            break

    else:

        hosts.append(rangefunc)

    return hosts

 

parser = ArgumentParser('pingrange')

parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23')

parser.add_argument('options', nargs='*', help='Options to pass to ping', default=['count 1'])

args = parser.parse_args()

targets = expandrange(args.ip)

for ip in targets:

    tupleping  = cli('ping %s %s' % (ip, ' '.join(args.options)))

    strping = str(tupleping)

    m = re.search('([0-9\.]+)% packet loss',strping )

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN'))

 

 

기존 pingrange의 변형된 코드의 달라진 점

      IP범위를 잘못 입력했을 경우에 예외 처리를 하였다.  (옥텟별로 1~255 사이)

             : checkRagne 메서드 정의.

             : 잘못된 입력인 경우에는 오류 메시지를 출력하고 시스템을 종료(sys.exit())를 한다.

      지정된 IP범위에서 증가값을 옵션으로 임의로 지정 할 수 있게 하였다.

              : 별도의 범위를 지정하지 않으면, default 1씩 증가한다.

 

 ◇ 기타 대부분의 코드는 아래의 변형된 코드와 유사하기 때문에 변형 코드의 주석과 기존 Part 2~4에서 다루었던 코드 이해하기

     이론 내용 등을 함께 보면 기존 코드를 이해하는 데 도움이 될 수 있을 것 같습니다.

 

 

pingrange Code : Modified Version

import sys                                                             # 시스템 패키지. 시스템 종료 메서드를 호출하기 위해 사용

import re                                                              # 정규식을 쓰기 위한 패키지

import cisco                                                         # Cisco 패키지  : Cli 명령을 사용하기 위해 사용.

from argparse import ArgumentParser               # 실행시의 매개변수를 다루기 위한 패키지

 

def checkRange(checkIP):                                       # 입력받은 IP 옥텟이 IP범위에 해당하는지 확인하기 위한 메서드

    octets = checkIP.split('.')                                  # 입력받은 IP를 '.으로 나눠서 각 옥텟별로 만듬

    for octet in octets:                                            # 각 옥텟이 저장된 List의 항목(IP의 각 옥텟)을 순환

        ip = int(octet)                                              # int 형 데이터로 변경

        if (ip < 0 or ip > 255):                                 # IP의 적정 범위인지 확인하여, 그 이외의 숫자인 경우에는 에러 발생

            print "Invalid Input Value"

            print "IP value is not less than 0 or greater than 255."

            sys.exit()                                                 # 시스템 종료

    return True

 

 

def expandrange(rangefunc,stepcnt):   # 사용자가 요청한 IP 범위 / 체크할 IP띄어쓸 범위

                                                                          # 체크할 IP 범위를 별도로 지정하지 않으면 1default 값으로 함.

    hosts = []                                                      # ping을 확인할 IP를 저장하기 위한 리스트 변수

    step = str(stepcnt[0])                                   # 매개변수 두번째를 리스트 type으로 받기 때문에 문자열 처리를 위해서 변경

    octets = rangefunc.split('.')                         # IP리스트를 옥텟별로 분리하여 LIST 변수에 저장

    for i,octet in enumerate(octets):                 # 옥텍별로 확인

        if '-' in octet:                                            # 만약에 옥텟안에 '-'이 있다면 해당 옥텟은 범위를 뜻하는 것.

            octetrange = octet.split('-')                # IP 범위를 LIST로 분리 (제일 앞 대역과 제일 대역)

            sip = int(octetrange[0])                      # IP 범위의 앞 부분을 sip로 int type으로 저장

            dip = int(octetrange[1])                     # IP 범위의 뒷 부분을 dip로 int type으로 저장

            for digit in range(sip,dip+1, int(step) if i==3 else 1):     

                                                                        # 순환문을 위한 값 지정 : 범위 지정의 첫번째 IP / IP / 증가값

                                         # 증가값의 경우에는 1~3번째 옥텟에는 해당하지 않고, 마지막 옥텟에만 해당되기 떄문에

                                         # 4번째 옥텟일 경우에만(i가 3인 경우가 옥텟이 4번째인 경우임, 0,1,2,3) 증가값을 적용하고

                                         # 그 이외의 경우에는 기본 증가값인 1을 사용한다.

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])   # 범위의 옥텟전 / 범위옥텟 / 범위 옥텟후를 더해서 IP로만듬

                                        # List의 경우 [] 안에 시작이나 종료점을 쓰지 않으면, 처음부터 끝까지를 나타냄.

                hosts += expandrange(ip,stepcnt)    # 옥텟에서 아직 범위가 있을 수 있기 때문에 다시 expandrage 호출

            break

    else:                                                                        # for문이 break로 종료되지 않고 정상 종료된 경우에 실행.

        if checkRange(rangefunc):                   # for문이 정상 종료된 경우 범위가 지정되지 않은 숫자로만 이뤄진 IP이나

            hosts.append(rangefunc)            # IP가 정상적인 IP범위에 해당하는지 checkRange메서드 호출해서 true인경우만

    return hosts                                          # Host에 IP를 추가하고 리턴해준다.

 

parser = ArgumentParser('AdvPing')

parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23')

                                                                # 매개변수 관리용 : 'ip' 이름으로 매개변수 1번째를 관리

parser.add_argument('options', type=str, default=['1'], nargs='*', help='Options to pass to ping')

                                                                # 매개변수 관리용 : 'options'로 처리하며, typestr로 하고 default값은 '1' 로 한다.

args = parser.parse_args()                     # 매개변수 손쉽게 사용하기 위해서 parse_args()메서드 호출

targets = expandrange(args.ip,args.options)    # IP와 option(IP 증가값)을 가지고 호출

for ip in targets:     # Ping을 체크할 전체 IP 리스트를 순환하면서 실행

    tupleping  = cisco.cli('ping %s' % ip)       # Ping 명령을 실행하고 그에 대한 결과값을 받음.

    strping = str(tupleping) # Tuple형식의 결과값을 str type으로 변형

    m = re.search('([0-9\.]+)% packet loss',strping ) # 정규식을 활용하여 IP가 UP/Down 확인

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN')) # 해당 IP의 UP/Down 표기

 

 

 

pingrange Code : Modified Version : 결과값

NX-OS# python pingrange2.py 10.9.8.1-200 32

10.9.8.1 - UP

10.9.8.33 - DOWN

10.9.8.65 - UP

10.9.8.97 - UP

10.9.8.129 - DOWN

10.9.8.161 - DOWN

10.9.8.193 - DOWN

 

Posted by 네떡지기
프로그래밍/Python2014.07.08 02:49

 


 

이번 포스팅은 지난 포스팅에 이어서 실제 Python 예제를 통해서 보려고 합니다.

기본 내용은 지난 포스팅과 이어지게 됩니다.  예제 소스는 기존 포스팅과 함께 왔다리 갔다리

하기 힘드실 듯하여... 해당 예제 포스팅이 끝날 때까지 계속 포함할 예정입니다. 

혹시 기존 포스팅을 보지 못하신 분은 반드시!

 

Python for Networker : Part 2

 

을 보고 오셔야 합니다.

 

본 내용에 사용된 에제는 아래에서 볼 수 있습니다.

[ 예제 링크 ] https://github.com/datacenter/who-moved-my-cli

 

※ 본 내용의 진행은 Nexus 5548 6.0(2)N2(4) 기준입니다.

 

 


 

pingrange.py

import re

from cisco import cli

from argparse import ArgumentParser

def expandrange(rangefunc):

    hosts = []

    octets = rangefunc.split('.')

    for i,octet in enumerate(octets):

        if '-' in octet:

            octetrange = octet.split('-')

            for digit in range(int(octetrange[0]), int(octetrange[1])+1):

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])

                hosts += expandrange(ip)

            break

    else:

        hosts.append(rangefunc)

    return hosts

 

parser = ArgumentParser('pingrange')

parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23')

parser.add_argument('options', nargs='*', help='Options to pass to ping', default=['count 1'])

args = parser.parse_args()

targets = expandrange(args.ip)

for ip in targets:

    tupleping  = cli('ping %s %s' % (ip, ' '.join(args.options)))

    strping = str(tupleping)

    m = re.search('([0-9\.]+)% packet loss',strping )

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN'))

 

❖ python 코드 실행 순서

  -  Active한 대화명 프롬프트 모드에서의 Python 실행이 아닌, Python 스크립트 코드를 보면서 어떻게 실행이 되는지

    혹시라도 헛갈리실 수 있을 듯 싶어서, 간단하게 위의 코드를 보면서 어떤 순서로 실행되는 보려고 합니다.

  - 우선 모든 코드는 제일 위에서부터 차례대로 진행이 되기 때문에 지난 Part 2에서 얘기된 필요한 Python 모듈을 먼저 Import

    하는 것으로 코드가 시작이 됩니다. 실제 아래 정의되는 실행부분에서 해당 모듈의 내용을 사용해야 하기 때문에 Python 모듈을

    Import하는 것이 당연히 제일 먼저 선언되어야 할 것입니다.

  - 그리고나서는 순서대로 실행이 되어야 하나, 위에서 보면 def 키워드로 expandrange() 함수가 선언되어 있습니다.

    함수는 바로 실행되지는 않기 때문에 expandrange() 함수 영역까지 (상단에서 보면 return host 부분)는 실제 바로 실행되지는

    않습니다.

  - 함수 선언부가 지난 이후에 일반 실행 코드가 순서대로 실행이 되게 됩니다.

  - 그리고 targets = expandrange(args.ip)에서 상단에 선언한 함수를 호출을 하게 됩니다. 그러면 당연히 Def로 선언한 함수

    선언부의 첫 줄부터 실행을 하게 되고, return host 부분까지 실행 후에는 해당 함수를 호출했던 라인으로 복귀를 하게 됩니다.

  - 그 다음에는 for문을 순환한 이후에 프로그램이 종료하게 됩니다.

  - 별다른 내용은 아니긴 하지만, 코드를 보면서 def나 class로(앞으로 다뤄질) 지정된 부분은 그 해당 라인에서 바로 실행이 아니라

    해당 내용을 사용하기 위한 선언부이기 때문에 실행 해당 내용이 실행되는 시점은 아래 실행 코드에서 해당 선언부를 호출하는

    경우가 되게 됩니다. 

 

 


 

 

 

python 문자열 다루기

      - Network 장비에서의 Python 사용에 있어서 가장 많이 활용하기 위해서 사용하는 부분이 문자열을 어떻게 다루느냐가 아닐 듯

       싶습니다.  물론 만약에 장비에서 얼마나 많은 종류의 자체 Python 모듈을 제공하느냐에 따라서 이 부분이 달라질 수 있을 듯

       싶지만, 그렇다고 하더라도 문자열을 가지고 활용할 수 있는 방법은 많을 것 같습니다. 이번 포스팅에서는 이런 문자열 다루기에

       대해서 다뤄봅니다. 아래 내용은 위의 코드를 이해하는 데 가장 많이 사용되는 부분이니, 꼭! 중요하게 읽어보셔야 할 것이라~

       생각해봅니다.

  

문자열 선언

   문자열을 선언하는 방법에는

       문자열’ , “문자열” , ‘’’다중라인 문자열‘’’, “””다중 라인 문자열“””

   •’, “ 모두 표기 가능하게 하여, 문자열 안에 를 넣으려고 할 때에는 문자열 안에 기호와 반대로 문자열을 묶어주면 안의

      기호는 문자열 기호가 아니라 단순히 ‘, “ 의 역할만 하게 된다.

       , “Network” ZIGI를 표현하고 싶을 경우에는 로 묶어서 ‘ “Network” ZIGI ‘ 쓰면 된다.

 

문자열 슬라이싱

   문자열[시작Idx:종료Idx-1]   : 문자열을 시작 Index 지점부터, 종료 Index – 1까지 의 문자열을 잘라낸다.

   시작 Index와 종료 Index를 각각 생략하게 되면, 각각 최초 시작 지점/종료 지점을 가리키게 된다.

 

❖ 문자열 연산

   문자열을 ‘+’로 합치는 경우에는 두 문자열 사이에 공백이 없이 합쳐지고, ‘,’로 합치는 경우에는 두 문자열 사이에 공백이

     들어가면서 합쳐지게 된다.

 

❖ 문자열 Formatting

   •print 시에 %s, %c, %d 등으로 지정하여 원하는 데이터 값을 출력 할 수 있다.

   Formatting 코드에 맞춰서 값을 넣어야 하지만, %s로 지정할 경우에는 자동 변환이 되서 들어가게 된다.

   문자열 내에 %를 사용하여 Formatting 시에는 %를 일반 문자로 출력하려면 %%로 써야 출력이 된다.

      하지만, 문자열 내에 % 사용한 Formatting이 없으면 그냥 %만 써도 된다.

   •%숫자s 과 같이 %Formatting 코드 사이에 숫자를 넣으면 해당 크기만큼 공간을 할당해서 출력하게 된다.

       이 때에 숫자를 로 입력하면 해당 공간만큼 할당하여 문자열을 왼쪽 정열하여 출력하게 된다.

  

%s 문자열 (String)

%c 문자 한개(character)

%d 정수 (Integer)

%f 부동소수 (floating-point)

%o 8진수

%x 16진수

%% Literal % (문자 '%s' 자체) 

 

Formatting Example Code

Example Code Result

print "I warn %d won." % 100

print "Americano %d won. Latte %d won" % (3900,4600)

print "My Name is %s" % ("Network ZIGI")

I warn 100 won.

Americano 3900 won. Latte 4600 won

My Name is Network ZIGI

print "%15s %s" % ("Network", "ZIGI")

print "%-15s %s" % ("Network", "ZIGI")

        Network ZIGI

Network         ZIGI

 

문자열 Method

•find(keyword, [start, [end]])   / rfind(keyword, [start, [end]])

     - 문자열에서 Keyword가 위치한 첫 번째(rfind는 뒤에서부터 첫 번째) Index리턴하고, 해당 Keyword가 존재하지 않으면

       ‘-1’을 리턴

•index(keyword, [start, [end]])

     - find() 와 동일한 동작을 하지만, Keyword가 존재하지 않을 경우에 ‘-1’이 아닌 ValueError 예외를 발생.

•join(sequence)

      - sequence 형변수를, Join을 호출한 문자열로 연결해서 리턴하는 메서드이며, split()와 반대의 역할을 하게 됨.

•partition(separator)

      - 문자열을 separator을 나누게 되는 데, separator , separator , separator 뒤의 3개의 Tuple로 리턴.

lstrip([chars])

      - 문자열의 왼쪽을 제거.chars을 지정하지 않으면 공백 문자를 제거.

 

 

Join / Partition / lstrip Example Code

 Join / Partition / lstrip Example Code Result

str1 = '-'

joinstr = str1.join("abc")

print(joinstr)

 a-b-c

str1 = "Network ZIGI Good"

partStr = str1.partition("ZIGI")

print(partStr)

part1 = partStr.__getitem__(2)

print(part1)

part1 = part1.lstrip()

print(part1)

 

('Network ', 'ZIGI', ' Good')

 Good

Good

 

•Split([separator, [maxsplit]])

      - separator로 문자열을 분리하는 것은 Partition과 동일하나, Partition의 경우에는 separator도 함께 리턴되지만,

        split는 해당 separator 기준으로 분리가 되면서 포함되지 않는다.

      - 뒤에 Maxsplit의 값을 주게되면, 앞에서부터 분리되는 개수의 max 값을 지정할 수 있다

Strip([chars])

      - 문자열 양쪽 끝을 잘라내는 데, 별도의 chars를 지정하지 않으면 공백을 제거하고 chars 지정 시에는 해당 문자가 포함된

        모든 내용이 삭제 된다

 

 

Split Example Code

Split Example Code

str1 = "Network ZIGI Good Split Test"

partStr = str1.partition("ZIGI")

print(partStr)

str2 = str1.split()

print(str2)

str3 = str1.split("ZIGI")

print(str3)

str4 = str1.split(' ',2)

print(str4)

 

('Network ', 'ZIGI', ' Good Split Test')

['Network', 'ZIGI', 'Good', 'Split', 'Test']

['Network ', ' Good Split Test']

['Network', 'ZIGI', 'Good Split Test']

 

 

 

Posted by 네떡지기

Last Updated : 2014.07.02

 


 

Network 장비에서 Python을 활용한 부분에 간단히 정리를 해보려고 합니다.

우선 처음 진행 부분은 현재 실제 테스트가 가능한 Nexus 7000 / 5000으로 먼저 간단히 시작합니다.

물론 완전 초기 부분이라서, 아마도 잘못된 부분 등에 대해서는 업데이트가 지속적으로 필요할 것 같습니다.

그리고 Nexus에서는 9000 / 3000 시리즈 기반으

Python 활용도가 더 높은 것으로 알고 있지만..(잘못 알고 있을수도? ^^)

현재 테스트가 가능한 부분이 Nexus 7000과 5000이라 이것으로 시작하며, 추후에 다른 테스트 장비(VM포함)로..

추가적인 포스팅을 진행할까합니다.

 

 


 

Cisco Nexus 7000  Python 특징

 Nexus 7K에서는 Python 2.7.2Interactive / noninteractive(script)에 대한 모드를 모두 지원합니다.

 NX-OS 6.2(8) 부터는 JavaScript Object Notation(JSON)logging module을 지원합니다.

 

 

Cisco Nexus 5000  Python 특징

 Nexus 5K에서는 Python 2.7.2모든 Feature를 사용할 수 있다.

 • Python Script를 이용하여 다음과 같은 기능을 구현할 수 있다.

       -  Swtich Bootup 시에 Configuration을 확인하는 Script 실행

       - Configuration 백업

       - Monitoring Buffer 이용량에 따라서, 사전에 혼잡 관리가 가능

       - 일정 시간 간격으로 작업을 수행

       - 프로그래밍 방식으로 SwitchCLI 명령을 수행하고 다양한 업무에 활용 가능

 

 

Third Party Pure Python Packages

 •Nexus에서 Third Party Python Package를 다음과 같은 방법으로 설치하고 사용할 수 있다.  

    ) ZIGI.tgz 를 서버로부터 복사하여 설치하는 경우.

     Step 1. 다음의 명령으로 tar fileSecure Copy 한다.

                      copy scp://user@server/path/to/ZIGI.tgz bootflash:ZIGI.tgz vrf management

     Step 2. Packge의 압축을 해제

                      tar extract bootflash:ZIGI.tgz

     Step 3. 압축이 풀린 Packgebootflash로 옮긴다

                      move bootflash:ZIGI/* bootflash:          

     Step 4. PackgeInstall 한다.

                      python setup.py install

     Step 5. bootflash에 복사된 파일을 제거한다.

     Step 6. Python Mode에서 해당 Packge를 사용한다.

                      NX-OS# python

                      >>> import ZIGI

 

 

 

Python Mode 접근

 

NX-OS# python

Python 2.7.2 (default, Nov 27 2012, 17:50:33)

[GCC 4.3.2] on linux2

Type "help", "copyright", "credits" or "license" for more  information.

Loaded cisco NxOS lib!

 >>> exit()

NX-OS#

 

 

 

 

Python 모드에서 Cli  명령 

 

 API

내  용 

1.  NX-OS# >>> cli("명령어")
    string = cli(“
명령어”)

 Python Mode에서 NexusCLI 명령어를 실행하고 Raw 결과를 리턴받게.

‘;’ 이용하여 다수의 명령어를 한 줄에 실행 가능

제어/특수 문자도 함께 출력. 이는 ‘\n’과 값도 함께 출력된다는 것을 의미하며,

    이는 가독성을 떨어지므로, clip() 명령을 사용하는 것이 보다 가독성에 좋다

2. NX-OS# >>> clid(“명령어”)

    dictionary= cli(“명령어”)

XML을 지원하는 CLI 명령어로 결과를 Dictionary 형식으로 리턴 받게 됨.

3. NX-OS#>>> Clip(“명령어”)

CLI 명령어에 대한 결과를 표준 Output으로 출력을 하며, 별도의 리턴 값은 없다.

 clip(“명령어”) r = cli(“명령어”) , print r  은 동일한 역할을 한다.

※ Nexus 7000 기준이며, Nexus 5000에서는 cli만 지원이 됩니다.

 

 Python Mode / CLI Mode 관련

 •Python Mode에서 Cli 명령을 사용하여 Switch Mode를 변경하는 경우에, Python Mode를 벗어나게 되면 변경된 Switch
   
Mode  유지되지는 않고, Python Mode 들어올 때의 기존 Mode로 가게 된다.

 •Python Mode에서 선언된 Data는 해당 Python Shell에서만 유효하며, Shell을 나간 후에 다시 들어오게 되면 사용 할 수 없게 된다. 

 

EX-1

EX - 2

NX-OS# python

NX-OS# >>> cli("conf t")

NX-OS(config)# >>> cli(“int e1/1”)

NX-OS(config-if)# >>> exit

NX-OS# 

NX-OS# python

NX-OS# >>> ZIGI = “JaeSung

NX-OS# >>> print ZIGI

JaeSung

NX-OS# >>> exit

NX-OS# python

NX-OS>>> pint ZIGI

Error:variable ‘ZIGI’ undefined

 

 

Posted by 네떡지기
프로그래밍/Python2014.05.09 00:50

 

Python 한 걸음 내딛기, 4번째 포스팅입니다.

일주일에 한개씩은 꼭! 지키려고 하다보니

이번에는 분량이 많지는 않습니다.

이번주 네전따 세미나가 있을 예정이라,

오늘 이외에는 올릴 수가 없을 듯 하여! ^^

짧게나마 이렇게 포스팅합니다.

다음 포스팅은 객체지향이 되지 않을까 싶습니다! ^^;

 

 


함수의 매개변수

- 함수를 호출할 때, 함수로 전달해주는 값으로 함수 처리 시에 필요한 내용을 적절하게 매개변수로 전달하여
사용할 수 있다.

- 파이썬에서는 '기본' , '키워드', '가변 리스트', '미정의 키워드' 에 대한 별도의 매개변수 전달 모드가
가능하며 각각의 사용법은 아래에서 알아보기로 한다.

   

기본 매개변수

- 함수 호출 시, 별도의 매개변수 값을 전달하지 않을 경우에 Default 값을 갖도록 함수 선언 시에 매개변수
별로 Default 값을 지정한 것이다.

- 이 경우에 함수를 별도의 매개변수를 전달하지 않으며, Default로 설정된 값으로 함수 내부에서 사용되며
만약 매개변수에 값을 전달할 경우에는 전달한 값으로 함수 내부에서 사용된다.

   

함수2 예제-1

함수2 예제-1 결과

def ParameterTest1(manager="네떡지기",vendor="cisco"):

        print(vendor,"장비 관리 : ",manager)

   

ParameterTest1()

ParameterTest1("고재성")

ParameterTest1("고재성","Arista")

cisco 장비 관리 : 네떡지기

cisco 장비 관리 : 고재성

Arista 장비 관리 : 고재성

   

   

   

키워드 매개변수    

- 함수 호출 시 전달되는 매개변수는 순서대로 함수의 선언 시에 순서와 동일하게 해당 값으로 매칭되어 전달
되지만, 이러한 순서와 상관없이 호출 시에 직접 매개변수의 키워드를 지정하여 전달할 수 있다.

   

함수2 예제-2

함수2 예제-2 결과

def ParameterTest2(manager,vendor):

       print(vendor,"장비 관리 : ",manager)

   

ParameterTest2(vendor="Fortinet",manager="고재성")

Fortinet 장비 관리 : 고재성

   

   

가변리스트 매개변수

- 함수 호출 시 전달되는 매개변수는 선언 시에 정의된 개수만큼만 전달을 할 수 있다.
하지만, 호출 시점마다 다른 개수의 매개변수를 전달해야 하는 경우가 있다. 이 경우에는 * 를 매개변수
앞에 써주게 되면 전달되는 매개변수를 튜플 형태로 전달을 받기 때문에 원하는 개수만큼 매개변수를
전달할 수 있게 된다.

함수2 예제-3

함수2 예제-3 결과

def ParameterTest3(manager, *vendors):

for ven in vendors:

       print("Manager-",manager,":", ven)

   

ParameterTest3("네떡지기","Cisco","Arista")

print("--------------------------")

ParameterTest3("고재성","DELL","HP","Juniper","Alteon")

Manager- 네떡지기 : Cisco

Manager- 네떡지기 : Arista

--------------------------

Manager- 고재성 : DELL

Manager- 고재성 : HP

Manager- 고재성 : Juniper

Manager- 고재성 : Alteon

 

함수2 예제-3 : Type확인

함수2 예제-3 :Type확인 결과

def ParameterTest3_Check(*vendors):

       print(type(vendors))

   

ParameterTest3_Check("Cisco","Arista")

<class 'tuple'>

   

   

미정의 키워드 매개변수

- 함수 호출 시 매개변수를 Data type중의 사전형식으로 매개변수를 전달하는 방법으로, 매개변수 앞에
** 를 써주게 되면 전달되는 매개변수를 사전형식으로 전달 할 수 있게 된다.

- 가변리스트 매개변수와 마찬가지로 원하는 개수를 전달할 수 있다.

   

함수2 예제-4

def ParameterTest4(cmd,**isps):

for isp in isps.keys():

       print("",isp,cmd,"Test")

       print(cmd,isps[isp])

   

ParameterTest4("ping",KT="168.126.63.1",LG="164.124.107.9",SK="210.220.163.82")

함수2 예제-4 결과

SK ping Test

ping 210.220.163.82

KT ping Test

ping 168.126.63.1

LG ping Test

ping 164.124.107.9

 

   

Posted by 네떡지기
프로그래밍/Python2014.05.01 22:28

1주일에 하나씩 목표로 하고 있는 Python 정리네요. ^^;

함수를 한 번의 포스팅으로 하려고 했는데.. 정리하다보니.. 살짝 길어져서.. 나눕니다. ^^;


함수

- 여러 줄의 명령을 하나의 범위로 지정하여 특정한 역할을 하도록 만든 것.
- 프로그램에서 여러 번, 사용해야 하는 일을 함수로 만들어서 필요 시 호출해서 사용할 수 있다.
- 직접 필요한 함수를 만들 수 있으며, 이미 만들어져 있는 함수를 호출해서 사용할 수도 있다.

   

함수 정의

- def <함수명> (매개변수1, 매개변수, ….):

명령문..

Return value

   

   

함수 예제로 함수 한걸음 내딛기

함수 예제-1)

함수 예제-2)

def SumFunc(a,b):

sum = a+b

return sum

   

print(SumFunc(10,20))

def printBlog():

print("http://ThePlmingSpace.tistory.com")

   

- def는 함수를 선언하는 Keyword 이다.

- 함수 선언 시, 매개변수는 함수 내에서 사용하게 될 변수를 함수 호출 시에 가져오는 것이다.

이러한 매개변수를 포함하여 함수를 선언할 수도 있고(예제1), 포함하지 않고 선언할 수 있다(예제2).

- 함수 선언 시, def Keyword와 함수명 뒤에는 ':' 을 써준다.

- 함수의 범위는 Python에서 늘 그러하듯이, Indent를 통해서 범위를 지정하게 된다.

- return은 함수를 종료 시에, 함수를 호출한 곳에 값을 넘겨주는 역할이며 넘겨줄 값이 없을 경우에는

생략이 가능하며 이 경우에는 None을 반환하게 된다. 이는 False가 되기도 한다.

※ if(printBlog()) 는 return 받는 값이 None이므로 False가 된다.

- 함수를 호출 시에는 반드시 함수명 뒤에 ( )를 써서 호출해야 한다.

함수도 하나의 객체로 취급되기 때문에, 함수명은 해당 함수 객체를 가리키는 변수일 뿐이다.

이를 이해하기 위해 아래 함수 예제-3을 보면,

   

함수 예제-3

함수 예제-3 : 결과값

def printNick_Name():

print("NetworkZIGI-네떡지기(고재성)")

   

print(printNick_Name)

print(printNick_Name())

<function printNick_Name at 0x01B18150>

NetworkZIGI-네떡지기(고재성)

None

   

- 예제-3에서 간단히 문장을 하나 출력하는 함수를 선언하고, 각각 함수명과 함수명()으로 호출을 하여 출력한다.

이에 대한 결과값을 보면, 함수명을 출력을 하게되면 이는 하나의 객체이기 때문에 해당 객체의 주소를 출력하

하게 된다. 그리고 정상적으로 함수() print 안에서 출력하면 해당 함수가 먼저 실행되기 때문에 함수에 선언한

내용이 먼저 출력이 되고, 함수에서는 별도의 return 값을 주지 않기 때문에 None을 받게 되고 이를 받은

print함수에서는 None을 출력하게 된다.

- 바로 위에서 설명 시에 얘기했던 것처럼, print 함수에서 함수를 호출했다. print도 바로 함수라는 점이고 이것이

처음에 얘기했던 기존에 선언되어 있는 Python의 내장함수가 되고, printNick_Name는 사용자 정의 함수가 된다.

   

함수에서의 범위(Scope), 한 걸음 내딛기 하나!

- Python의 Scope는 Indent로 구분이 되고, 함수도 마찬가지이다.

- 모든 변수는 자신이 선언된 Scope 내에서만 유효하다. 따라서, 함수 안에서 선언된 변수는 함수 안에서만 유효

하며, 함수의 Scope를 벗어나면 해당 객체는 사용할 수 없다.

- 모든 변수는 자신이 선언된 Scope 내에서만 유효하다는 것은, 자신의 Socpe를 포함한 자신 Scope 안에서

선언된 하위 Scope 안도 포함되게 된다. Scope를 벗어나서 사용이 불가하다는 것은 결국 상위 Scope에서는

하위 Scope에 선언된 내용을 알 수 없다는 것이다.

- 예제 4를 보면, scopeTest 함수 내에서 nick이라는 변수를 만들어서 사용하였고,

real이라는 변수는 상위 Scope(여기서는 전역공간임)에 선언하여 사용하였다.

- 이 경우에 scopeTest 내에서는 모두 접근이 가능한 변수이기 때문에, 정상적으로 출력이 되지만,

외부에서 name과 nick을 접근하려고 하면, real은 동일한 scope이기 때문에 접근이 되지만

nick는 함수 내에서 선언된 변수이기 때문에 외부 scope에서는 알 수가 없고, 따라서 nick이라는 변수가

선언된 적이 없다고 오류가 발생하게 된다.

   

함수 예제-4

함수 예제-4 결과값

real = "고재성"

   

def scopeTest1():

nick = "네떡지기"

print(nick)

print(real)

   

scopeTest1()

print(real)

print(nick)

네떡지기

고재성

고재성

File "C:/FunctionTest.py", line 12, in <module>

print(nick)

NameError: name 'nick' is not defined

   

   

   

함수에서의 범위(Scope), 한 걸음 내딛기 둘!

- 함수의 매개변수로 전달되는 것은, 실제 변수의 값이 있는 주소를 전달하게 된다.

- 매개변수로 전달받은 값을 새로운 값으로 변경을 하면, 실제 원래의 값이 변경되는 것이 아니라 새로운 값의

의 주소로 바뀌게 되는 것 뿐이다.

- 예제-5를 보면, real이라는 변수를 함수 호출 시 전달을 하게 되고, scopeTest2 함수 내에서는 이 값을 보면

실제 기존에 선언된 값이 있는 주소 값을 그대로 가리키고 있음을 볼 수 있고, 만약에 새로운 값을 할당하면

해당 변수는 새로운 값이 있는 주소 값으로 바뀌게 된다. 하지만, 함수를 벗어나게 된 이후에 원래의 real을

보면 여전히 기존의 값을 유지하고 있음을 알 수 있다.

- 만약 함수 외부에 선언된 변수와 함수 내부에 선언된 변수가 있을 경우에는 함수 내부에서 선언된 것이

더 우선하게 된다. 만약에 자신의 Scope 내에 없는 경우에는 상위 Scope를 확인하게 된다.

이는 어쩌면 너무나도 당연하다, 내가 쓰려고 하는 것이 여러 개 있으면 가장 가까운 것을 가져다 쓰는 것이다.

- 함수 내부에서 전역영역에서 선언한 변수를 그대로 가져와서 쓸 수도 있는 데, 이는 global이라는 keyword를

사용하여 함수 내부에서 동일한 변수 명으로 변수를 선언한다. 이 경우에는 함수 내부에서 값을 변경하면

그대로 반영되게 된다.

- 예제-6을 보면, real과 nick을 함수 외부(전역영역)에서 선언했고, scopreTest3에서 동일한 이름의 변수를

사용을 하는데, real이라는 변수는 그냥 동일한 이름으로 사용을 하고 nick은 global keyword를 사용한다.

그리고, 각 새로운 값으로 초기화해서 써서 출력하면 함수 내에서는 초기화한 값으로 출력이 되고

함수를 나와서, 각 변수를 출력하면, global을 써서 함수 내에서 쓴 nick만 변경된 것을 볼 수 있다.

함수 내에서 전역공간의 변수를 가져다가 사용하기 위한 예제라고 볼 수 있다.

   

함수 예제-5

함수 예제-5 결과값

함수 예제-6

함수 예제-6 결과값

real = "고재성"

   

def scopeTest2(name):

print(id(name))

name = "네떡지기"

print(name)

print(id(name))

   

print(id(real))

scopeTest2(real)

print(id(real))

print(real)

20301248

20301248

네떡지기

28458784

20301248

고재성

real = "고재성"

nick = "고재성"

   

def scopeTest3():

real = "네떡지기"

global nick

nick = "네떡지기"

print(real)

print(nick)

   

scopeTest3()

print(real)

print(nick)

네떡지기

네떡지기

고재성

네떡지기

   

- 함수 예제 5/6의 경우를 이해하기 위해 간단한 개념도(?) 정도로 아래의 그림을 보면..

 

- 일반적인 매개변수 전달 시인 예제5의 경우에는 real을 매개변수로 전달하게 되면,

real이 가지고 있는 '고재성'이라는 값의 주소를 복사하여 새로운 공간(200)에 할당해서 사용한다.

이 경우에는 name이 가리키는 곳의 공간(1000)이 동일하기 때문에 그 값을 그대로 쓸 수 있지만

만약 이 값을 새로운 값으로 변경하게 되면 해당 값이 있는 공간(2000)을 가리키도록 변경된다.

하지만, 이 경우에는 real이라는 값에는 영향을 미치지 않는다.

   

 

- Global keyword를 사용하게 되면, 개념적으로 그냥 전역변수의 nick을 그대로 쓴다고 이해해도 되겠지만

위의 그림과 같이 함수 내에서의 nick(g-nick으로 표기)이 전역변수와 동일한 곳을 가리키도록 하고,

그 곳에는 실제 값이 있는 공간(1000)을 지칭하는 값이 있다.

이 때 함수 내의 nick의 값을 변경하게 되면, 전역공간과 동일한 곳(100)에 새로운 값을 가리키는 값(2000)을

넣기 때문에 전역 공간의 값에도 함께 영향을 받게 된다.

   

Posted by 네떡지기
프로그래밍/Python2014.04.23 21:39

~위한 파이썬.. 이라는 Title을 가져보려고 하는데.. 잘 될지 모르겠네요.

타이틀을 어찌할지도.. ^^;

오늘부터... 가능하면 이 주제에 대해서도 1주일에 하나씩은 하려고 합니다.

기존에 1회성(?) 스터디 때 사용한 자료가 있어서.. 이번 주까지는 1번 더 올릴 수 있을 듯 싶고..

다음 주부터는.. 공부하고 만들어야 할 듯요.. ^^;

자꾸 더디게 움직이는 듯하여... 스스로를 채찍질하기 위한.. 일종의 프로젝트성. ^^;


 

 

 Indentation

Python에서 Code Block(Scope)을 구분하는 방법

동일한 Code Block 내에서는 동일한 방법(Space, Tab)으로 구분해야 함.

         가독성을 좋게 하기 위해 전체적으로 동일한 방법으로 작성

하위 레벨의 Code Block이 나오기 바로 전에는 ‘ : ’ (콜론)을 사용.

Indent를 지키지 않으면 오류 발생

 

 

 

 

변수

 

별도의 변수 Type이 존재하지 않는다

변수명으로 문자 / 숫자 / ‘_’ 사용가능하며 대소문자를 구분

지정한 값에 따라서 알맞은 변수 Type으로 인식을 하게 된다.

객체 단위로 지정이 되며, 별도의 초기화 없이 바로 사용이 가능하다.

동일 객체인지 id(변수명) 명령을 사용하여 확인할 수 있다. id는 일종의 메모리 참조 값이다.

 

수치형 자료

숫자를 나타내는 자료형

int, long, float, complex 등이 있다

        ※ Python 3.0에서는 long형은 없어지고 int형으로 처리

선언 시에, 사용자가 입력한 값에 따라서 적정한 수치형  Type으로 선언된다

 

 문자열

 

 문자열은 기본적으로 " " 혹은 ' ' 로 묶어주게 된다.

러 줄의 문자열은 ''' (홑따음표) 3개를 앞 뒤로 묶어준다.   

  일반 " " 로 구성된 문자열 내부에 ', ''을 표기하기 위해서는 \를 붙여서 쓴다.  이를 escaping 이라고 부른다.

 문자열 내부에는 다른 변수의 값을 포함하여 출력할 수 있는 데,  변수가 포함될 위치에 %s를 붙인다

    이후, print 시에 %를 쓰고 뒤에 해당 %s에 들어갈 변수명을 입력한다. 이를 Placeholder라고 한다.

    만약 2개 이상의 변수를 포함하고 싶으면, 출력 시 % 뒤에 변수명을 기입할 때 ( )로 묶어준다.

 문자열을 반복하여 입력하거나 출력할 수 있는 데, 단순히 반복할 문자열 뒤에 *와 반복될 수를

     입력하면 된다. 마치 문자열을 필요한 만큼 곱해서 사용하는 것과 같다.

 

 리스트

다수의 객체를 하나의 객체로 관리하는 것.

대괄호 [ ]로 묶어주고, 대괄호 내에서는 ',' 로 각 객체를 구분하게 된다.

대괄호 안의 항목들은 각각의 index position을 가지게 되고, index0부터 시작한다.

index를 사용하여서 필요한 항목을 사용할 수 있으며, 다른 항목으로 변경도 가능하다.

대괄호 안의 index 사용 시에 ':'을 사용하면, index의 구간을 지정할 수도 있다.

     (ex : My_list[3:7]    - My_list3Index부터 6Index까지의 항목을 지정:마지막 전까지 포함)

 

 

 

리스트에 항목을 추가하려고 할 때에는 append / insert / extend 함수를 사용할 수 있다

리스트의 항목을 삭제 시에는 del List_Variable[Index] 으로 삭제가 가능하다.

두 개의 List의 항목을 합치기 위해서는 List 객체를 + 연산을 이용해서 그냥 더해주면 된다.

     마찬가지로 동일한 내용의 List를 반복하려면 * 연산자를 사용하면 된다.

 

 

 세트

 리스트와 유사하게 다른 객체들의 집합으로 이루어진다.

{ }로 묶어서 정의
교집합과 합집합을 구하는 별도의 메서드가 제공된다.

       교집합 : union  /   합집합 : intersection

차집합 / 합집합 / 교집합을 구하는 연산자가 제공된다.

       교집합 : &  /   합집합 : |  /  차집합 : -

 

 튜플

다수의 객체를 하나의 객체로 관리하는 것은 리스트와 동일하지만

   리스트는 초기 생성 후에 수정이 가능하지만, 튜플을 수정을 할 수 없다.

읽기 전용으로 사용되기 때문에 제공하는 메서드가 적지만 속도가 빠르다.  

괄호 ( )로 묶어주고, 괄호 안에서 ','로 각 객체를 구분하게 된다.

 

 

 

 Dictionary /사전 /

다수의 객체를 하나의 객체로 관리하는 것은 리스트와 동일하지만,

   다수의 객체를 하나의 객체로 관리하는 점에서 리스트나 튜플과 동일하지만,

    각 객체의 값에는 특정한 keyMapping되어 있다.

중괄호 { }로 묶어주고, 중괄호 내에서는 ','로 각 객체를 구분하며,

    하나의 객체는 ':'keyValueMapping 시킨다.     [ key : Value ]

    (ex : Mobile_Phone = { 'Samsung' : 'Galaxy' , 'Apple' : 'I-Phone', 'LG' : 'Cyon' }

dict(key={ ,key=} ) 으로 선언할 수도 있다.

맵에 있는 객체를 'key'를 이용해서 가져오거나, 수정하거나, 삭제할 수 있다.

      그러나 List 처럼 + / * 를 통한 연산은 불가능 하다.

 

 

 

 

연산자

In

리스트, 세트, 튜플에서 사용되며, 해당 자료형 내부에 특정한 값이 존재하는지 확인하여 True/FalseReturn.

 

 

Posted by 네떡지기

티스토리 툴바