task07

1、以下类定义中哪些是类属性,哪些是实例属性?

class C:
num = 0 #类属性
def init(self):
self.x = 4 #实例属性
self.y = 5 #实例属性
C.count = 6 #类属性
类属性:类里面方法外面定义的变量称为类属性。类属性所属于类对象并且多个实例对象之间共享同一个类属性,说白了就是类属性所有的通过该类实例化的对象都能共享。

【例子】

class A():
    a = 0  # 类属性

    def __init__(self, xx):
        # 使用类属性可以通过 (类名.类属性)调用。
        A.a = xx

实例属性:实例属性和具体的某个实例对象有关系,并且一个实例对象和另外一个实例对象是不共享属性的,说白了实例属性只能在自己的对象里面使用,其他的对象不能直接使用,因为self是谁调用,它的值就属于该对象。

【例子】

class 类名():
    __init__(self):
        self.name = xx #实例属性
类属性和实例属性区别

类属性:类外面,可以通过实例对象.类属性和类名.类属性进行调用。类里面,通过self.类属性和类名.类属性进行调用。
实例属性 :类外面,可以通过实例对象.实例属性调用。类里面,通过self.实例属性调用。
实例属性就相当于局部变量。出了这个类或者这个类的实例对象,就没有作用了。
类属性就相当于类里面的全局变量,可以和这个类的所有实例对象共享。
【例子】

# 创建类对象
class Test(object):
    class_attr = 100  # 类属性

    def __init__(self):
        self.sl_attr = 100  # 实例属性

    def func(self):
        print('类对象.类属性的值:', Test.class_attr)  # 调用类属性
        print('self.类属性的值', self.class_attr)  # 相当于把类属性 变成实例属性
        print('self.实例属性的值', self.sl_attr)  # 调用实例属性


a = Test()
a.func()

# 类对象.类属性的值: 100
# self.类属性的值 100
# self.实例属性的值 100

b = Test()
b.func()

 # 类对象.类属性的值: 100
 # self.类属性的值 100
 # self.实例属性的值 100

a.class_attr = 200
a.sl_attr = 200
a.func()

 # 类对象.类属性的值: 100
 # self.类属性的值 200
 # self.实例属性的值 200

b.func()

 # 类对象.类属性的值: 100
 # self.类属性的值 100
 # self.实例属性的值 100

Test.class_attr = 300
a.func()

 # 类对象.类属性的值: 300
 # self.类属性的值 200
 # self.实例属性的值 200

b.func()
 # 类对象.类属性的值: 300
 # self.类属性的值 300
 # self.实例属性的值 100
注意:属性与方法名相同,属性会覆盖方法。

【例子】

class A:
    def x(self):
        print('x_man')


aa = A()
aa.x()  # x_man
aa.x = 1
print(aa.x)  # 1
aa.x()  # TypeError: 'int' object is not callable

2、怎么定义私有方法?
私有方法:以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。

class Site:
    def __init__(self, name, url):
        self.name = name  # public
        self.__url = url  # private

    def who(self):
        print('name  : ', self.name)
        print('url : ', self.__url)

    def __foo(self):  # 私有方法
        print('这是私有方法')

    def foo(self):  # 公共方法
        print('这是公共方法')
        self.__foo()


x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name  :  老马的程序人生
# url :  https://blog.csdn.net/LSGO_MYP

x.foo()
# 这是公共方法
# 这是私有方法

x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'

3、尝试执行以下代码,并解释错误原因:

class C:
    def myFun():
        print('Hello!')
    c = C()
    c.myFun()

运行结果:

Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/untitled/task04.py", line 1, in <module>
    class C():
  File "C:/Users/Administrator/PycharmProjects/untitled/task04.py", line 4, in C
    c = C()
NameError: name 'C' is not defined

4、按照以下要求定义一个游乐园门票的类,并尝试计算2个成人+1个小孩平日票价。

要求:

平日票价100元
周末票价为平日的120%
儿童票半价

class Ticket():
    def __init__(self, date, adult, child):
        if date == 'work':
            self.price = 100
        else:
            self.price = 120
        self.child= child #儿童个数
        self.adult = adult #成人个数
        self.fees = 0
    def __childfee(self):
        self.fees += int(self.price * self.child * 0.5)#儿童票的总费用,其中儿童票半价
    def __adultfee(self):
        self.fees += int(self.price * self.adult)#成人票的总费用
    def calculatefee(self):
        self.__childfee()
        self.__adultfee()
        print("共花%d元"%self.fees)
z = Ticket('work',2,1) #工作日情况下2个成人1个孩子总票价
z.calculatefee()

运行结果:共花250元
5.上面提到了许多魔法方法,如__new__,init, str,rstr,getitem,__setitem__等等,请总结它们各自的使用方法。
init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法
【例子】

class Rectangle:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getPeri(self):
        return (self.x + self.y) * 2

    def getArea(self):
        return self.x * self.y


rect = Rectangle(4, 5)
print(rect.getPeri())  # 18
print(rect.getArea())  # 20

new(cls[, …]) 在一个对象实例化的时候所调用的第一个方法,在调用__init__初始化前,先调用__new__。
new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init
new__对当前类进行了实例化,并将实例返回,传给__init__的self。但是,执行了__new,并不一定会进入__init__,只有__new__返回了,当前类cls的实例,当前类的__init__才会进入。
【例子】

class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(cls, *args, **kwargs)


b = B(10)

# 结果:
# into B __new__
# 
# into A __new__
# 
# into B __init__

class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(A, *args, **kwargs)  # 改动了cls变为A


b = B(10)

# 结果:
# into B __new__
# 
# into A __new__
# 

若__new__没有正确返回当前类cls的实例,那__init__是不会被调用的,即使是父类的实例也不行,将没有__init__被调用。
【例子】利用__new__实现单例模式。

class Earth:
    pass


a = Earth()
print(id(a))  # 260728291456
b = Earth()
print(id(b))  # 260728291624

class Earth:
    __instance = None  # 定义一个类属性做判断

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            return cls.__instance


a = Earth()
print(id(a))  # 512320401648
b = Earth()
print(id(b))  # 512320401648

__new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。
【例子】

class CapStr(str):
    def __new__(cls, string):
        string = string.upper()
        return str.__new__(cls, string)


a = CapStr("i love lsgogroup")
print(a)  # I LOVE LSGOGROUP

del(self) 析构器,当一个对象将要被系统回收之时调用的方法。
Python 采用自动引用计数(ARC)方式来回收对象所占用的空间,当程序中有一个变量引用该 Python 对象时,Python 会自动保证该对象引用计数为 1;当程序中有两个变量引用该 Python 对象时,Python 会自动保证该对象引用计数为 2,依此类推,如果一个对象的引用计数变成了 0,则说明程序中不再有变量引用该对象,表明程序不再需要该对象,因此 Python 就会回收该对象。

大部分时候,Python 的 ARC 都能准确、高效地回收系统中的每个对象。但如果系统中出现循环引用的情况,比如对象 a 持有一个实例变量引用对象 b,而对象 b 又持有一个实例变量引用对象 a,此时两个对象的引用计数都是 1,而实际上程序已经不再有变量引用它们,系统应该回收它们,此时 Python 的垃圾回收器就可能没那么快,要等专门的循环垃圾回收器(Cyclic Garbage Collector)来检测并回收这种引用循环。

【例子】

class C(object):
    def __init__(self):
        print('into C __init__')

    def __del__(self):
        print('into C __del__')


c1 = C()
# into C __init__
c2 = c1
c3 = c2
del c3
del c2
del c1
# into C __del__

str(self):
当你打印一个对象的时候,触发__str__
当你使用%s格式化的时候,触发__str__
str强转数据类型的时候,触发__str__
repr(self):
repr是str的备胎
有__str__的时候执行__str__,没有实现__str__的时候,执行__repr__
repr(obj)内置函数对应的结果是__repr__的返回值
当你使用%r格式化的时候 触发__repr__
【例子】

class Cat:
    """定义一个猫类"""

    def __init__(self, new_name, new_age):
        """在创建完对象之后 会自动调用, 它完成对象的初始化的功能"""
        self.name = new_name
        self.age = new_age

    def __str__(self):
        """返回一个对象的描述信息"""
        return "名字是:%s , 年龄是:%d" % (self.name, self.age)
        
    def __repr__(self):
        """返回一个对象的描述信息"""
        return "Cat:(%s,%d)" % (self.name, self.age)

    def eat(self):
        print("%s在吃鱼...." % self.name)

    def drink(self):
        print("%s在喝可乐..." % self.name)

    def introduce(self):
        print("名字是:%s, 年龄是:%d" % (self.name, self.age))


# 创建了一个对象
tom = Cat("汤姆", 30)
print(tom)  # 名字是:汤姆 , 年龄是:30
print(str(tom)) # 名字是:汤姆 , 年龄是:30
print(repr(tom))  # Cat:(汤姆,30)
tom.eat()  # 汤姆在吃鱼....
tom.introduce()  # 名字是:汤姆, 年龄是:30

str(self) 的返回结果可读性强。也就是说,str 的意义是得到便于人们阅读的信息,就像下面的 ‘2019-10-11’ 一样。

repr(self) 的返回结果应更准确。怎么说,repr 存在的目的在于调试,便于开发者使用。

【例子】

import datetime

today = datetime.date.today()
print(str(today))  # 2019-10-11
print(repr(today))  # datetime.date(2019, 10, 11)
print('%s' %today)  # 2019-10-11
print('%r' %today)  # datetime.date(2019, 10, 11)

6.利用python做一个简单的定时器类

要求:

定制一个计时器的类。
start和stop方法代表启动计时和停止计时。
假设计时器对象t1,print(t1)和直接调用t1均显示结果。
当计时器未启动或已经停止计时时,调用stop方法会给予温馨的提示。
两个计时器对象可以进行相加:t1+t2。
只能使用提供的有限资源完成。

import time
class timer():
    def __init__(self):
        self.__initt = '计时尚未开始'
        self.__begin = None
        self.__end = None
        self.__time = 0

    def __str__(self):
        return self.__initt

    def __repr__(self):
        return self.__initt

    def start(self):
        print("开始计时")
        self.__begin = time.localtime()

    def stop(self):
        if not self.__begin:
            print("请先调用start()开始计时")
            return
        self.__end = time.localtime()
        self.__time = time.mktime(self.__end) - time.mktime(self.__begin)
        self.__initt = '运行了%f秒' % self.__time
        print("结束计时")
        return self.__time

    def __add__(self, other):
        return 't1+t2共运行了%f秒' % (self.__time + other.__time)


t1 = timer()
print(t1)
t1.stop()
t1.start()
time.sleep(1)
t1.stop()
print(t1)
t2 = timer()
t2.start()
time.sleep(2)
t2.stop()
print(t2)
print(t1 + t2)

运行结果:计时尚未开始
请先调用start()开始计时
开始计时
结束计时
运行了1.000000秒
开始计时
结束计时
运行了2.000000秒
t1+t2共运行了3.000000秒

你可能感兴趣的:(task)