Python基礎筆記(五)

1. 類(class)

下面的代碼創建了一個Employee類:python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

class Employee(object):
    
    company = "IBM"

    def __init__(self, name, sex, age, salary):
        self.name = name
        self.sex = sex
        self.age = age
        self.__salary = salary

    def getSignature(self):
        signature = "My name is %s, I'm %d years old." % (self.name, self.age)
        return signature

    def getSalary(self):
        return self.__salary

    def setSalary(self, salary):
        if 0 < salary <= 10000:
            self.__salary = salary
        else:
            raise ValueError("Invalid Value")

tom = Employee("tom", "male", 23, 3000)

print(tom.getSignature())
# My name is tom, I'm 23 years old.

print(tom.age)
# 23

tom.setSalary(5000)
tom.__salary = 9000 # 無效,實際上是新增了一個名爲"__salary"的變量
print(tom.getSalary())
# 5000

__init__方法至關於其它語言的「構造函數」,該方法的第一個參數必須爲self,self表明建立的實例自己,所以在__init__方法內部能夠把各類屬性綁定到self;在實際調用時,self並不須要傳遞,Python解釋器本身會把實例變量傳進去。
以一個下劃線開頭的變量名,例如_company,這種變量外部是能夠訪問的,可是按照約定俗成的規定,這種變量應該視爲私有變量,不要隨意訪問。
以兩個下劃線開頭的變量名,例如__salary,是私有變量,外部不能直接訪問,通常提供"get"和"set"方法去間接獲取和修改。
開頭與結尾都是兩個下劃線,例如__name__,是特殊變量,特殊變量是能夠直接訪問的。
須要注意的是,當在一個外部類嘗試用下面的代碼訪問新建的Employee類時,是會報錯的:函數

import Employee

tom = Employee("tom", "female", "23")

報錯內容爲TypeError: 'module' object is not callable,這個錯誤是指試圖把模塊做爲一個函數來調用。產生錯誤的緣由是,import Emplyee實際上是導入了整個的Employee.py,而不是名爲Employee的類。正確的作法有兩種:ui

(1) 用「模塊名.類名「來訪問:code

import Employee

tom = Employee.Employee("tom", "male", 23, 6000)

(2) 用"from...import..."的形式導入對象

from Employee import *

tom = Employee("tom", "male", 23, 6000)

2. 獲取對象的類型

type(obj)函數返回參數的對象類型,基本類型如intstr也能夠用它來判斷:utf-8

from Employee import *

tom = Employee("tom", "male", 23, 6000)

print(type(23))
# <class 'int'>

print(type("ABC"))
# <class 'str'>

print(type(tom))
# <class 'Employee.Employee'>

if type(123) == type(456):
    print("Equal")

if type("ABC") == str:
    print("Equal")

print(type(tom) == Employee)
# True

可使用types模塊中定義的常量來判斷一個對象是不是函數,lambda函數或generator:字符串

import types

def myFun():
    pass

# 是不是函數
print(type(myFun) == types.FunctionType)
# True

# 是不是內置函數
print(type(abs) == types.BuiltinFunctionType)
# True

# 是不是lambda函數
print(type(lambda x: x)==types.LambdaType)
# True

# 是不是generator
print(type((x for x in range(10)))==types.GeneratorType)
# True

能用type()判斷的基本類型也能夠用isinstance()判斷:get

print(isinstance(23,int))
# True

print(isinstance("ABC", str))
# True

print(isinstance(b"A", bytes))
# True

print(isinstance(tom, Employee))
# True

isinstance()還能夠用於判斷一個對象是不是某些類型中的一種:generator

print(isinstance("23", (str, int)))
# True

print(isinstance([1, 2, 3], (list, tuple)))
# True

3. 獲取對象的屬性和方法

若是要得到一個對象的全部屬性和方法,可使用dir(obj)函數,它返回一個包含字符串的listit

print(dir("ABC"))
# ['__add__', '__class__', ... , 'upper', 'zfill']

相似__xxx__的屬性和方法在Python中都是有特殊用途的,好比__len__方法返回長度。在Python中,若是你調用len()函數試圖獲取一個對象的長度,實際上,在len()函數內部,它自動去調用該對象的__len__()方法,因此,下面的代碼是等價的:

print(len("ABC"))

print("ABC".__len__())

下面的例子證實了len()會調用__len__()方法:

class MyClass1(object):
    def __len__(self):
        return 100

class MyClass2(object):
    pass

myClass = MyClass1()
print(len(myClass))
# 100

myClass = MyClass2()
print(len(myClass))
# TypeError: object of type 'MyClass2' has no len()

4. hasattr、getattr和setattr

利用這三個方法,能夠判斷對象是否有某屬性/方法,獲取指定名稱的屬性/方法,新增屬性等操做:

class Employee(object):
    def __init__(self, name, sex, age, salary):
        self.name = name
        self.sex = sex
        self.age = age
        self.__salary = salary

    def getSignature(self):
        signature = "My name is %s, I'm %d years old." % (self.name, self.age)
        return signature

employee = Employee("tom", "male", 23, 3000)

# 判斷對象是否有"age"屬性,有則打印並賦值
if hasattr(employee, "age"):
    print(employee.age)
    employee.age = 18

# 若是對象沒有"hobby"屬性,則新增該屬性並賦值
if not hasattr(employee, "hobby"):
    setattr(employee, "hobby", "music")

# 經過getattr獲取對象指定的屬性值
print(getattr(employee, "hobby"))
# music

# 若是試圖獲取不存在的屬性,會拋出AttributeError的錯誤:
# getattr(employee, "gold")
# AttributeError: 'Employee' object has no attribute 'gold'

# 利用getattr的第三個參數:若是屬性不存在,就返回一個默認值
print(getattr(employee, "gold", "not exist"))
# not exist

# 經過getattr獲取方法,注意:若是方法不存在,會拋出AttributeError
print(getattr(employee, "getSignature"))
# <bound method Employee.getSalary of <__main__.Employee object at 0x10832a4a8>>

# 判斷是否存在指定名稱的方法,若是存在,則執行該方法
try:
    funcName = "getSignature"
    func = getattr(employee, funcName)
    if hasattr(func, "__call__"):
        print("存在方法", funcName)
        # 存在方法 getSignature
        print(func())
        # My name is tom, I'm 18 years old.
except AttributeError as e:
    print("沒有方法:", funcName)
相關文章
相關標籤/搜索