一、实例属性和类属性
1、类属性
- 类属性是所有的是实例对象共用的属性
- 它可以通过实例对象和类对象来获取
- 类属性不能通过实例对象来修改!!!
- 想修改类属性时,需要访问到该类属性
2、实例属性
- 实例属性:每创建一个实例对象,都会在实例对象上添加这个属性
3、实例方法
class Person(object):
money = 10000
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
print('我是test方法')
p = Person('张三', 18)
print(hex(id(p)))
p1 = Person('李四', 23)
print(hex(id(p1)))
print(hex(id(Person)))
print(p.money)
print(p1.money)
print(Person.money)
p.money = 20000
print(p.money)
print(p1.money)
print(Person.money)
p1.money = 100
Person.money = 3000
print(p.money)
print(p1.money)
print(Person.money)
二、实例方法、类方法和静态方法
1、实例方法
- 当实例对象调用实例方法的时候,会自动的把实例对象 p 传递给 test 函数里 self参数;
- 类对象也可以调用实例方法,但是,不会自动的给方法的 self 传参类;
- 对象调用实例方法的时候,需要手动的给方法的self传参,不推荐使用
2、类方法
- 使用 @classmethod 装饰器来说明;
- 有一个参数,参数是 cls,表示的类对象(def demo(cls)) ;
- cls 参数,表示的是类对象,类方法一般配合类属性使用;
- 只能访问类属性,不能访问到实例属性;
- 类方法可以通过类对象、和实例对象来调用;
- 需要使用类属性时候,使用类方法
3、静态方法
- 使用 staticmethod 装饰器
- 函数不需要任何的参数(def foo()):;
- 可以理解为一个普通的函数,直接附着到了一个对象上;
- 默认不能够访问到类属性,不能访问到实例属性;
- 既不需要访问类属性,也不需要使用实例属性,使用静态方法
class Person(object):
__type = '人类'
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
print('我是{}'.format(self.name))
@classmethod
def demo(cls):
return cls.__type
@staticmethod
def foo():
print('我是Foo函数')
print(Person.__type)
def bar():
print('呵呵')
p = Person('jerry', 12)
p.test()
Person.test(p)
Person.demo()
print(p.demo())
p.foo()
Person.foo()
三、__new__方法
- __new__根据类对象申请一段内存空间,并返回 return object.new(cls)
- __init__方法填入数据,自动把 __init__里的 self 参数指向第一步里申请好的内存空间
class Person(object):
def __new__(cls, *args, **kwargs):
print('__new__方法被调用了!!!')
return object.__new__(cls)
def __init__(self, name, age):
print('__init__方法被调用了!!!')
self.name = name
self.age = age
p = Person('zhangsan', 18)
print(p)
三、单例设计模式
- 单例设计模式:第一次创建时候是什么样子,后续创建到所有都一样;
- 加判断是否是第一次使用逻辑后,如果是,那后续都同第一次
class Person(object):
__instance = None
__is_first = True
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, name, age):
if self.__is_first:
self.name = name
self.age = age
self.__is_first = False
def test(self):
print(Person.__is_first)
p1 = Person('zhangsan', 18)
p2 = Person('lisi', 20)
print(p1 is p2)
print(hex(id(p1)))
print(hex(id(p2)))
print(p1.name)
print(p2.name)
p2.test()
四、射击游戏
class Gun(object):
def __init__(self, model, damage, bullet_count=0):
self.model = model
self.damage = damage
self.bullet_count = bullet_count
def add_bullet(self, count):
self.bullet_count += count
def shoot(self, x):
if self.bullet_count <= 0:
print('没有子弹,不能开枪')
return
self.bullet_count -= 1
print('开了一枪,还剩{}发子弹'.format(self.bullet_count))
x.hurt(self)
class Player(object):
def __init__(self, name, hp, gun=None):
self.name = name
self.hp = hp
self.gun = gun
def hurt(self, enemy_gun):
if self.hp <= 0:
print('已经死了,就不要再鞭尸了!!!')
return
self.hp -= enemy_gun.damage
print('{}被{}打了,掉了{}血,还剩{}血'.format(self.name, enemy_gun.model, enemy_gun.damage, self.hp))
def fire(self, enemy):
if not self.gun:
print('你还没有枪!')
return
if not self.gun.bullet_count:
print('没有子弹,自动装填子弹!')
self.gun.add_bullet(30)
self.gun.shoot(enemy)
gun1 = Gun('m416', 10)
p1 = Player('张警官', 100, gun1)
p2 = Player('王土匪', 80)
p1.fire(p2)
五、异常处理
1、异常处理的基本语句
try except as
import os
file_name = '05-射击游戏案例.py'
if os.path.exists(file_name):
file = open(file_name, encoding='utf-8')
print(file.read())
else:
print('你要操作的文件不存在')
try:
1 / 0
file = open('test.txt', encoding='utf-8')
except:
print('出问题了!要操作的文件不存在')
try:
2 / 0
file = open('test.txt', encoding='utf-8')
except FileNotFoundError:
print('出问题了!文件不存在异常')
try:
1 / 0
file = open('test.txt', encoding='utf-8')
except (FileNotFoundError, ZeroDivisionError):
print('出错了!,文件不存在异常或除数为0异常')
try:
1 / 0
file = open('test.txt', encoding='utf-8')
except (FileNotFoundError, ZeroDivisionError) as e:
print(e)
2、finally
- try…finally…保证finally代码块里的内容一定会被执行;
- 如果一个函数里有finally语句,finally语句里的代码也一定会执行;
file = open('01-实例属性和类属性.mp4', 'rb')
try:
while True:
content = file.read(1024)
print(content)
if not content:
break
finally:
print('文件被关闭了')
file.close()
def test(a, b):
try:
c = a + b
return c
finally:
return 'hehe'
print(test(1, 2))
3、with关键字的使用
- with关键字能够自动帮忙执行 close 方法,但不能处理异常;
- with 是上下文管理器,with后面的对象,要有 enter 和 __exit__方法;
- 不是任意的一个代码都能放到 with关键字后面;
- 如果要在 with 后面,对象必须要实现 enter 和 __exit__方法
- 读取文件异常中断时(打开文件和关闭文件),使用with,可以自动把文件关闭;
- socket通信时(需要打开和关闭),也可以用with
with open('test.txt') as f:
f.read()
class Demo(object):
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
1 / 0
print('我是test方法')
def __enter__(self):
print('我是enter方法,我被执行了')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('我是exit方法,我被执行了')
print('exc_type={},exc_val={},exc_tb={}'.format(exc_type, exc_val, exc_tb))
d = Demo('lisi', 18)
d.test()
with Demo('zhangsan', 15) as d:
d.test()
4、抛出异常
常见的异常: ValueError FileNotFoundError ZeroDivisionError TypeError SyntaxError StopIteration PermissionError NameError ModuleNotFoundError
def do_cal():
num1 = int(input('请输入一个数字:'))
if num1 < 0:
raise ValueError
x = pow(num1, 0.5)
print(x + 5)
try:
do_cal()
except ValueError as e:
print('程序出现了错误!')
5、自定义异常
1、自定义异常
class NegativeSqrtError(BaseException):
def __str__(self):
return '负数不能开方!!!'
def do_cal():
num1 = int(input('请输入一个数字:'))
if num1 < 0:
raise NegativeSqrtError
x = pow(num1, 0.5)
print(x)
try:
do_cal()
except NegativeSqrtError as e:
print(e)
2、例子 让用户输入密码,如果密码的长度不满足 [6,11] 位,抛出 PasswordError 打印错误信息时,输出内容是 ‘密码长度必须是6到11位!!!’
class LengthError(Exception):
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return '密码长度必须是{}到{}位!!!'.format(self.x, self.y)
def get_password():
min_length = 6
max_length = 11
password = input('请输入您的密码:')
if len(password) < min_length or len(password) > max_length or password.isdigit() == False:
raise LengthError(min_length, max_length)
return password
try:
pwd = get_password()
print(pwd)
except Exception as e:
print(e)
|