类是一个具有相同特征和相同方法的群体的集合。每个类会开辟一个地址空间,实例化的对象也会被分配另外一个地址空间,并指向之前的类。
1、基础的类
class Person(object):
name="zhangsan"
age=30
gender="男"
def runn(self):
print("I can run")
def talk(self):
print("I can speak")
#实例化一个对象
p1=Person()
#调用一个对象方法
p1.runn()
2、装饰器
class Person(object):
name="zhangsan"
age=30
gender="男"
@classmethod
def runn(cls):
print("I can run")
print(cls.name)
@staticmethod
def talk():
print("I can speak")
#实例化一个对象
p1=Person()
#调用一个对象方法
p1.runn()
#调用类方法。类方法可以调用自己的属性和方法,一般用做工具类
Person.runn()
#调用静态方法
Person.talk()
"""
执行结果:
I can run
zhangsan
I can run
zhangsan
I can speak
"""
3、类的初始化方法
class Person(object):
name="zhangsan"
age=30
gender="男"
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
print(name,age,gender)
def jump(self):
print("%s can jump."%self.name)
@classmethod
def runn(cls):
print("I can run")
print(cls.name)
@staticmethod
def talk():
print("I can speak")
#实例化一个对象
p1=Person("lisi",39,"男")
p1.runn()
p1.jump()
p1.name="yuan"
p1.runn()
p1.jump()
Person.name="lulu"
p1.runn()
p1.jump()
"""
执行结果:
lisi 39 男
I can run
zhangsan
lisi can jump.
I can run
zhangsan
yuan can jump.
I can run
lulu
yuan can jump.
由以上可以看出对象和类属于不同的地址存储空间
"""
4、类的继承和方法的覆盖
class Animal(object):
name="poppy"
age=1
def run(self):
print("i can run")
def bat(self):
print("i can bat")
class Dog(Animal):
def __init__(self,name,age):
self.name=name
self.age=age
#覆盖父方法
def run(self):
print("%s can run"% self.name)
d1=Dog("kaka",3)
d1.run()
d1.bat()
"""
执行结果:
kaka can run
i can bat
"""
5、type,isinstance函数使用
class Animal(object):
name="poppy"
age=1
def run(self):
print("i can run")
def bat(self):
print("i can bat")
class Dog(Animal):
#覆盖父方法
def run(self):
print("%s can run"% self.name)
p1=Dog()
print(type(p1))#<class '__main__.Dog'>
print(isinstance(p1,Dog))#True
print(isinstance(p1,Animal))#True
6 、dir(obj)返回对象的所有属性和方法,obj.__dict__返回自定义的实例属性字典
class Dog(object):
#类属性
name="shsh"
def __init__(self,age,gender):
#实例属性
self.age=age
self.gender=gender
def run(self):
print("i can run")
p1=Dog(23,'男')
print(p1.__dict__)
print(dir(p1))
"""
执行结果:
{'age': 23, 'gender': '男'}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'gender', 'name', 'run']
"""
6、类的内置方法__str__和__repr__
__str__改变对象的字符串显示,调用print()的时候会自动调用__str__方法,直接调用str(obj)
__repr__是在解释器里会加载的方法,程序员用的比较多repr(obj)
7 、__new__方法
在解释器执行类的实例化的时候加载的方法,实例化一次就开辟一个空间
以下是单例模式的示范
class Person(object):
flag=None
@staticmethod
def __new__(self):
if self.flag==None:
self.flag=super().__new__(self)
return self.flag
def __init__(self):
pass
def run(self):
print("i can run")
p1=Person()
p2=Person()
p3=Person()
print(id(p1))
print(id(p2))
print(id(p3))
"""
执行结果:
140396062985376
140396062985376
140396062985376
PS:最先执行__new__,然后才会执行__init__,单例模式不会重新开辟新的空间给实例。默认不是单例模式,只有特别情况才会使用
"""
8、私有类型和保护类型
类中类似__init__这种的方法是类的内置方法
类似__name前面两个下划线表示私有变量,只允许本类进行调用
类似_name前面有一个下划线的表示受保护类型的变量,只有本类和子类进行调用
class Person(object):
flag=None
__name="luluu"
__age=23
def __init__(self,age):
self.__age=age
class Teacher(Person):
pass
t1=Teacher(24)
print(dir(t1))
print(t1._Person__age)
"""
执行结果:
['_Person__age', '_Person__name', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'flag', 'run']
24
PS:通过__var子类无法访问父类,而父类可以直接访问自己。外部只能通过演变的名称去访问私有变量
"""
在继承中,父类如果不想让子类继承自己的方法可以在方法前面加两个下划线,使方法私有化,同属性的定义一致
9、属性装饰器@property和@name.setter(私有属性)
可以使属性通过.方法进行设置
class Person(object):
def __init__(self,name,age):
self.__name=name
self.__age=age
@property
def name(self):
return self.__name
@name.setter
def name(self,name):
self.__name=name
p1=Person("haha",28)
print(p1.name)#haha
p1.name="lulu"
print(p1.name)#lulu
10、多态
from abc import ABCMeta, abstractmethod # (抽象方法)
class Payment(metaclass=ABCMeta): # metaclass 元类 metaclass = ABCMeta表示Payment类是一个抽象类
def __init__(self, name, money):
self.money = money
self.name = name
@abstractmethod # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
def pay(self, *args, **kwargs):
pass
class AliPay(Payment):
def pay(self):
# 支付宝提供了一个网络上的联系渠道
print('%s通过支付宝消费了%s元' % (self.name, self.money))
class WeChatPay(Payment):
def pay(self):
# 微信提供了一个网络上的联系渠道
print('%s通过微信消费了%s元' % (self.name, self.money))
class Order(object):
@staticmethod
def account(pay_obj):
pay_obj.pay()
pay1 = WeChatPay("yuan", 100)
pay2 = AliPay("alvin", 200)
order = Order()
order.account(pay1)
order.account(pay2)
"""
执行结果:
yuan通过微信消费了100元
alvin通过支付宝消费了200元
"""
11、反射
反射指程序能够修改,检测,访问自己对象的状态或行为的一种能力
# 1.hasattr(object,name): 判断对象中有没有一个name字符串对应的方法或属性
# 2.getattr(object, name, default=None): 获取对象name字符串属性的值,如果不存在返回default的值
# 3.setattr(object, key, value): 设置对象的key属性为value值,等同于object.key = value
# 4.delattr(object, name): 删除对象的name字符串属性
12、异常机制
异常的分类:
- 异常有很多种类型,Python内置了几十种常见的异常,无需特别导入,直接就可使用。
- 需要注意的是,所有的异常都是异常类,首字母是大写的!
异常的危害:
-
如果程序中一旦出现了异常的语句代码,则该异常就会立即中断程序的运行!
-
因此:为了保证程序的正常运行,提高程序健壮性和可用性。我们应当尽量考虑全面,将可能出现的异常进行处理,而不是留在那里,任由其发生。
try:
pass # 正常执行语句
except Exception as e:
pass # 异常处理语句
finally:
pass # 无论是否发生异常一定要执行的语句,比如关闭文件,数据库或者socket
使用方式可嵌套、可区分优先级
try:
pass # 正常执行语句
except <异常名1>:
pass # 异常处理语句1
except <异常名2>:
pass # 异常处理语句2
except <异常名3>:
pass # 异常处理语句3
可用逗号统一使用
try:
pass # 正常执行语句
except (<异常名1>, <异常名2>, ...):
pass # 异常处理语句
自定义异常需要继承Exception大类,间接继承也是可以的
-
raise可以抛出自定义异常
# 1.用户自定义异常类型
class TooLongExceptin(Exception):
"this is user's Exception for check the length of name "
def __init__(self, len):
self.len = len
def __str__(self):
return "输入姓名长度是" + str(self.len) + ",超过长度了"
try:
name = input("enter your name:")
if len(name) > 5:
raise TooLongExceptin(len(name))
else:
print(name)
except TooLongExceptin as error: # 这里异常类型是用户自定义的
print("打印异常信息:", error)