python进阶(课程学习笔记)

简述Python中的实例方法,类方法,静态方法

1. 实例方法:

    与具体的实例相关,会传入一个必须的参数self。self代表被实例化的对象本身。实例方法中能够访问在构造函数__init__()中方初始化的成员变量。

2. 类方法:

   与类本身相关的方法。会传入一个必须的参数cls。cls表示当前类,无法通过cls访问构造函数__init__()中创建的成员变量。但是可以在类方法中修改类属性。类方法声明时,需要使用装饰器classmethod进行修饰

3.静态方法:

   静态方法,与对象以及类均无关系,不需要传递额外的参数。静态方法需要使用装饰器@staticmethod进行修饰。

# 实例方法
class Person:

    country = "china"      # 类属性 / 需要与self.xxx类数据成员进行区别

    def __init__(self, name, age, occupation):
        """
        属性定义
        :param name:         public
        :param age:          protected
        :param occupation:   private
        """
        self.name = name
        self._age = age
        self.__occupation = occupation

    def eat(self):
        """
        实例方法,因为第一个参数是self(具体的实例),参数是实例
        :return:
        """
        print("{} is eating.".format(self.name))

    @classmethod
    def greet(cls):
        """
        类方法,需要添加装饰器,且第一个参数必须是cls(class,类),参数是类
        :return:
        """
        cls.country = "Russion"      # 可以在类方法中修改类属性country
        print("Hello Everyone, I am from {}".format(cls.country))

        # print("Name is {}".format(cls.name))   # 通过cls也无法访问类中的数据成员

    @staticmethod
    def static_test():
        """
        静态方法不需要传递self或者cls参数,他的操作跟当前的类或者对象没有关系
        :return:
        """
        print("This is a static method")


if __name__ == "__main__":
    p1 = Person("Sam", 31, "Doctor")
    p1.eat()         # 实例方法
    # Person.eat()     # 报错,无法调用

    Person.greet()   # 类方法,只能通过类调用
    p1.greet()       # 也可以调用

    # 通过类和对象均可调用静态方法
    Person.static_test()
    p1.static_test()

4. python中的继承:

    python中实现继承法的方式如下所示:

    继承的public,protected类型的数据成员在子类中可以直接访问,private成员无法直接进行访问,续通过调用父类的方式进行获取。

# encoding: utf-8

class Person:
    """
    define class person
    """
    def __init__(self, name, age, occupation):
        self.name = name
        self._age = age
        self.__occupation = occupation

    def get_occupation(self) -> str:
        return self.__occupation

    def get_person_info(self):
        print("My name is {}, I am {} years old and I am a {}".format(self.name, self._age, self.__occupation))

    @staticmethod
    def _get_passwd(self) -> str:
        return "123"


class Student(Person):
    def __init__(self, name, age):
        super(Student, self).__init__(name, age, "Student")   # 调用父类的构造函数

    def print_name(self):
        print("My name is {}".format(self.name))              # 继承的public成员

    def print_age(self):
        print("My age is {}".format(self._age))               # 继承的protected成员

    def print_occupation(self):
        print("My work is {}".format(super(Student, self).get_occupation()))  # 父类的private在子类中无法直接访问


if __name__ == "__main__":
    s = Student("Sam", 22)
    s.print_name()
    s.print_age()
    s.print_occupation()

5. __new__(cls, *args, **kwargs)

    __new__()是用来控制类实例化对象的创建流程,这个方法在对象还没创建之前就会执行,__init__()方法是在创建对象完成执行的。

# encoding: utf-8

class Person:
    def __new__(cls, *args, **kwargs):
        """
        __new__()方法执行完毕后,一定要返回父类Object的__new__方法调用,且只能传递参数cls
        :param args:
        :param kwargs:
        """
        print("Call the new method!")
        # 打印参数
        print(args)
        print(kwargs)
        return super().__new__(cls)      # 这里必须要返回对象,如果不反悔,则实例化的对象始终为None

    def __init__(self, name):
        self.name = name
        print("Name is {}".format(name))


if __name__ == "__main__":
    p = Person("Elly")

执行结果:

若存在继承的情况:

# encoding: utf-8

class Person:
    def __new__(cls, *args, **kwargs):
        """
        __new__()方法执行完毕后,一定要返回父类Object的__new__方法调用,且只能传递参数cls
        :param args:
        :param kwargs:
        """
        print("Call the new method!")
        # 打印参数
        print(args)
        print(kwargs)
        return super().__new__(cls)      # 这里必须要返回对象,如果不反悔,则实例化的对象始终为None

    def __init__(self, name):
        self.name = name
        print("Name is {}".format(name))


class Student(Person):
    def __new__(cls, *args, **kwargs):
        print("Call the new method student")
        return super().__new__(cls, name=args[0])  # 父类不是object,可以将参数传递给父类的__new__()方法

    def __init__(self, name):
        self.name = name


if __name__ == "__main__":
    # p = Person("Elly")
    s = Student("Sam")
    

 执行结果:

 6. Python中的单例设计模式

     某个类在程序运行期间只能有一个对象被创建:

# 单例设计

class User:

    __instance = None      # 定义私有的类属性

    def __new__(cls, *args, **kwargs):
        """
        在__new__方法中,判断类属性__instance是否为None,如果为None,调用super().__new__()进行创建,赋值给类属性__instance
        如果__instance已经不为None,则直接返回__instance,这样保证了不管在程序运行中实例化了多少次对象,只会返回最初实例化的那
        个对象,实现对象的全局唯一。
        :param args:
        :param kwargs:
        """
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self):
        pass

    @classmethod
    def get_user(cls):
        return User()


if __name__ == "__main__":
    user1 = User.get_user()
    user2 = User.get_user()

    print(id(user1))
    print(id(user2))

可以看到实例化两次后返回的是同一个对象:

 设计线程安全的单例模式:在上述的单例模式中,如果一个线程在实例化对象的过程中,判断到类属性__instance为None,则会去super().__new__()创建一个新的对象,如果此时实例化过程未结束,类属性__instance依然为空,另一个线程又去实例化对象,则后面线程创建的对象会将前面线程创建的对象覆盖。

7. 异常处理:

   具体语法格式

if __name__ == "__main__":
    a = 3
    b = 0
    c = 0
    try:                    # 捕获异常的区域
        c = a / b
    except Exception:       # 捕获的异常的具体类型,Exception表示捕获所有异常
        print("Exception appeared!")
    else:
        print("Result is {}".format(c))  # 没有捕获到异常
    finally:
        print("End the routine")         # 不管有没有异常都会执行的代码区域

可以写多个except捕获多种类型的异常:

if __name__ == "__main__":
    a = 3
    b = 5
    c = 0
    try:                    # 捕获异常的区域
        c = a / b
        print(d)            # 未定义变量
    except ZeroDivisionError:       # 捕获的异常的具体类型,Exception表示捕获所有异常
        print("Can not divide zero!")
    except NameError:
        print("variable is not defined!")
    else:
        print("The result is {}".format(c))  # 没有捕获到异常
    finally:
        print("End the routine")         # 不管有没有异常都会执行的代码区域

也可以通过下面的方式打印异常信息:

    except NameError as error:
        print("variable is not defined!")
        print(error.args)

8. 抛出异常:

def greet(name, age):
    """
    :param name:
    :param age:
    :return:
    """
    if not isinstance(name, str):
        raise TypeError("name must be a string.")     # 抛出异常
    if not isinstance(age, int):
        raise TypeError("age must be int")            # 抛出异常

    print("I am {} and {} years old".format(name, age))


if __name__ == "__main__":
    try:
        greet("Tom", "1")
    except TypeError as error:
        print(error.args)

9. 自定义异常

自定义异常需要继承自Exception类

def greet(name, age):
    """
    :param name:
    :param age:
    :return:
    """
    if not isinstance(name, str):
        raise ArgumentError("name must be a string.")     # 抛出异常
    if not isinstance(age, int):
        raise ArgumentError("age must be int")            # 抛出异常

    print("I am {} and {} years old".format(name, age))


class ArgumentError(Exception):

    def __init__(self, *args, **kwargs):
        tmp_args = args + ("参数错误", )
        super(ArgumentError, self).__init__(*tmp_args)


if __name__ == "__main__":
    try:
        greet("Tom", "1")
    except ArgumentError as error:
        print(error.args)

python常见异常:

python常见异常
异常名称异常说明
AttributeError属性错误,访问一个对象的不存在的属性的时候,抛出这个异常
ImportError导入包错误
IndexError下标错误,一般有列表越界等
KeyErrorkey错误,一般访问字典的key不存在的时候
NameError变量名不存在
NotImplementedError某个方法没有实现的错误
StopIteration迭代器已经到最后了
IndentationError缩进错误
TabError包含了tab和空格错误
TypeError类型错误,有时候传递了一个错误类型的值给其他函数
UnicodeEncodeErrorUnicode编码错误,一般是unicode->str错误
UnicodeDecodeErrorUnicode解码错误,一般是str->unicode错误
ValueError值错误,比如传一个12a给int()函数转换
ZeroDivisionError除0错误
IOError打开一个不存在的文件(在Python3中使用FileNotFoundError)
FileNotFoundError文件没有找到的错误

9. python模块导入

在大型项目中,将所有的代码都放到一个文件中不利于代码维护。python中通过模块和包将不同文件中相关的代码整合到一个文件中。

python中的包:包本质上是一个文件夹,将相关的模块组合到一起。如果一个文件夹想被python识别为一个包,则必须在这个文件夹中创建一个__init__.py的文件。此时这个文件夹就能被python识别为一个包。在一个包中的模块,通过import可以相互导入。

在python中导入包,在使用import的时候,是按照特定的路径去查询相应的包是否存在,可以通过sys模块来查询路径的列表,在import相应的包的时候,python是按照如下的路径列表去查找代码中的包或者模块是否存在:

import sys
print(sys.path)

 python会按照上述的路径列表进行查找相应的包。

包中的模块在执行import导入模块的时候,可以采用两种方式,相对路径导入和绝对路径导入

from ..modulename import     相对路径上级目录

form .modulename import      相对路径当前目录

__all__变量:可以控制from modulename import * 的行为,如果__all__ = [ ]列表中指定了相应的变量,函数,或者类,import * 的时候只会导入__all__变量中的内容。

在__init__.py中导入的模块,才可以通过包名直接导入,否则不会导入成功,可以在__init__.py中通过__all__ = [ ] 控制import *的导入行为。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值