zoukankan      html  css  js  c++  java
  • Python基础笔记(五)

    1. 类(class)

    下面的代码建立了一个Employee类:

    #!/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的类。正确的做法有两种:
    (1) 用“模块名.类名“来访问:

    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也可以用它来判断:

    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()判断:

    print(isinstance(23,int))
    # True
    
    print(isinstance("ABC", str))
    # True
    
    print(isinstance(b"A", bytes))
    # True
    
    print(isinstance(tom, Employee))
    # True
    

    isinstance()还可以用于判断一个对象是否是某些类型中的一种:

    print(isinstance("23", (str, int)))
    # True
    
    print(isinstance([1, 2, 3], (list, tuple)))
    # True
    

    3. 获取对象的属性和方法

    如果要获得一个对象的所有属性和方法,可以使用dir(obj)函数,它返回一个包含字符串的list

    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)
    
  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/10938991.html
Copyright © 2011-2022 走看看