python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod

python中的接口概念

在python中根本就没有一个叫做interface的关键字,如下的代码只是看起来像接口,其实并没有起到接口的作用

利用NotImplementedError

class Payment:
    def pay(self):
        raise NotImplementedError

class ApplePay(Payment):
    def zhifu(self,money):
        print("ApplePay zhifu %d" % money)

#必须实现pay方法,否则报错NotImplementedError
    # def pay(self):
    #     print("ApplePay pay")

app = ApplePay()
app.zhifu(200)
#ApplePay必须实现,才调用不报错
app.pay()

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
Traceback (most recent call last):
  File "E:/python/py_pro/python.py", line 51, in <module>
    app.pay()
  File "E:/python/py_pro/python.py", line 38, in pay
    raise NotImplementedError
NotImplementedError
ApplePay zhifu 200

Process finished with exit code 1

所以我们通过raise NotImplementedError方式,强制其子类,实现方法,才能不报错,将上面代码注释去掉,然后就可以顺利输出如下的正确信息:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
ApplePay zhifu 200
ApplePay pay
利用abstractmethod

注意事项:
子类必须全部实现重写父类的abstractmethod方法
非abstractmethod方法可以不实现重写
带abstractmethod方法的类不能实例化

#接口类
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass

    @abstractmethod
    def get(self, money):
        print("Payment get%d" % money)

    def total(self,money):
        print("Payment total %d" % money)

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

class AppPay(Payment):
    def pay(self,money):
        print("AppPay pay %d"%money)

    def get(self,money):
        print("AppPay get %d" % money)

app = AppPay("safly")
app.pay(100)
app.get(200)
app.total(400)
# 不能实例化
# TypeError: Can't instantiate abstract class Payment
# with abstract methods get, pay
# a = Payment("safly")

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
<__main__.AppPay object at 0x01201E30>
AppPay pay 100
AppPay get 200
Payment total 400

抽象类

与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

from abc import ABCMeta,abstractmethod
class Base(metaclass=ABCMeta):
    def __init__(self,fName):
        self.fName = fName;

    @abstractmethod
    def open(self):pass

class File(Base):
    def open(self):
        print("file open")

file = File("safly")
file.open()

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
file open

多态概念

在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同


from abc import ABCMeta,abstractmethod
class Base(metaclass=ABCMeta):
    @abstractmethod
    def talk(self):
        pass

class Pig(Base):
    def talk(self):
        print("pig talk")


class People(Base):
    def talk(self):
        print("People talk")

def talk(obj):
    obj.talk()

pig = Pig()
people = People()
pig.talk()
people.talk()

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
pig talk
People talk

__属性封装

私有静态属性、私有方法
print("------封装-------")
#封装
#把属性、方法藏在类里面,在类内部调用
class Dog:
    # 私有静态属性
    __kind = "wangcai"

    #调用私有静态属性
    def getKind(self):
        return Dog.__kind
    #私有方法
    def __func(self):
        print("__func")
    #调用私有方法
    def func(self):
        self.__func()

#如下调用不提倡
print(Dog.__dict__)
print(Dog._Dog__kind)

#如下调用错误,因为需要在类内调用
# print(Dog.__kind)

d = Dog()
print(d.getKind())

#如下调用不提倡
d._Dog__func()
d.func()

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
------封装-------
{'__module__': '__main__', '_Dog__kind': 'wangcai', 'getKind': <function Dog.getKind at 0x02BB1F60>, '_Dog__func': <function Dog.__func at 0x02BB1F18>, 'func': <function Dog.func at 0x02BB1ED0>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
wangcai
wangcai
__func
__func
私有对象属性
#私有对象属性

class Room:
    def __init__(self,name,area):
        self.name = name
        self.__area = area

    def getArea(self):
        return self.__area

room = Room("safly",100)
print(room.name)
print(room.getArea())
#不能如下方法调用私有对象属性
# print(room.__area)

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
safly
100
私有属性不能被继承
#私有方法不能被继承
class A:
    __role = "role"
    def __func(self):
        print("__a func")

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

class B(A):
    #如下的方法是错误的
    def getRole(self):
        return B.__role

a = A("safly")
print(dir(a))
print("-------------")
b = B("safly")
print(dir(b))

#调用报错AttributeError: type object 'B' has no attribute '_B__role'
# print(b.getRole())

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
['_A__func', '_A__name', '_A__role', '__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__']
-------------
['_A__func', '_A__name', '_A__role', '__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__', 'getRole']

property 方法转属性

@property 把一个方法 伪装成一个属性
1.属性的值 是这个方法的返回值
2.这个方法不能有参数了
3.类不能调用,只能对象调用

class Person:
    def __init__(self,name,height,weight):
        self.name = name
        self.height = height
        self.weight = weight
    @property
    def bmi(self):
        return self.weight / (self.height**2)

    @property
    def methdd(self):
        print("method")

per = Person("safly",1.73,75)
print(per.bmi)
per.methdd
#如下调用没有效果
Person.methdd

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
25.05930702662969
method

property-setter设置值

class Goods:
    discount = 0.8
    def __init__(self,name,price):
        self.name = name
        self.price = price

    @property
    def getPrice(self):
        return self.price * Goods.discount

    @getPrice.setter
    def getPrice(self,newPrice):
        self.price= newPrice


app = Goods("apple",10)
print(app.getPrice)

app.getPrice = 20

print(app.getPrice)

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
8.0
16.0

deleter



class Foo:
    name = "Foo"
    @property
    def AAA(self):
        print('get的时候运行我啊')

    @AAA.setter
    def AAA(self,value):
        print('set的时候运行我啊',value)

    @AAA.deleter
    def AAA(self):
        del Foo.name
        print('delete的时候运行我啊')

#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()

f1.AAA
#setter
f1.AAA='aaa'
print(Foo.name)
#deleter
del f1.AAA
#删除完毕后,再次调用报如下错误
#AttributeError: type object 'Foo' has no attribute 'name'
# print(Foo.name)

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
get的时候运行我啊
set的时候运行我啊 aaa
Foo
delete的时候运行我啊

在del f1.AAA后,删除完毕后,再次调用print(Foo.name)报如下错误
AttributeError: type object ‘Foo’ has no attribute ‘name’

内置property函数

一个静态属性property本质就是实现了get,set,delete三种方法

class Foo:
    def get(self):
        print('get的时候运行我啊')

    def set(self,value):
        print('set的时候运行我啊',value)

    def delet(self):
        print('delete的时候运行我啊')
        #def __init__(self, fget=None, fset=None, fdel=None, doc=None)
    AAA=property(get,set,delet) #内置property三个参数与get,set,delete一一对应

f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
get的时候运行我啊
set的时候运行我啊 aaa
delete的时候运行我啊

classmethod

下面代码中我分别列出了,在不使用classmethod类方法,和使用类方法的2种写法
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数
不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来


#classmethod
#需要使用静态变量,且不需要跟对象相关
class Goods:
    __discount = 0.8

    @classmethod
    def change(cls,newPrice):
        cls.__discount = newPrice
    @classmethod
    def getPrice(cls):
        return cls.__discount

#之前的使用方式
    def change1(self,newPri):
        Goods.__discount = newPri
    def getPrice1(self):
        return Goods.__discount

Goods.change1(Goods,30)
print(Goods.getPrice1(Goods))

Goods.change(20)
print(Goods.getPrice())

输出如下:

E:\python\python_sdk\python.exe E:/python/py_pro/python.py
30
20

staticmethod

staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。

class A:
    def func(self,name):
        print(name)

    def func1(name):
        print(name)

    @staticmethod
    def func2(self,name):
        print(name)

    @staticmethod
    def func3(name):
        print(name)


A.func(A,"safly")
A.func1("safly")

A.func2(A,"safly")
A.func3("safly")

输出如下:

safly
safly
safly
safly

总结类、对象可以调用的方法



# staticmethod self\cls失效,类对象、实例对象均可以调用
# classmethod cls不管类对象、实例对象,输出均是类对象
class A:
    @staticmethod
    def func1(name):
        print("func1",name)

    @staticmethod
    def func2(self,name):
        print("func2",self,name)

    @classmethod
    def func3(cls):
        print("func3",cls)

    @classmethod
    def func4(cls,name):
        print("func4",cls,name)

    @classmethod
    def func5(self,name):
        print("func5",self,name)

    @classmethod
    def func6(cls,self,name):
        print("func6",cls,self, name)

    def func7(self,name):
        print("func7",name)

    def func8(name):
        print("func8",name)

print("-----类调用--------")
A.func1("safly")
A.func2("A","safly")
A.func3()
A.func4("safly")
A.func5("safly")
A.func6("A","A")
A.func7(A,"safly")
A.func8("safly")

# print("----对象调用------")
a = A()
a.func1("safly")
a.func2("A","safly")
a.func3()
a.func4("safly")
a.func5("safly")
a.func6("A","A")
a.func7("safly")
a.func8()

输出如下:

E:\python\py_dev\venv\Scripts\python.exe "E:/python/py_dev/python/03 python模拟登陆MysQL版.py"
-----类调用--------
func1 safly
func2 A safly
func3 <class '__main__.A'>
func4 <class '__main__.A'> safly
func5 <class '__main__.A'> safly
func6 <class '__main__.A'> A A
func7 safly
func8 safly
func1 safly
func2 A safly
func3 <class '__main__.A'>
func4 <class '__main__.A'> safly
func5 <class '__main__.A'> safly
func6 <class '__main__.A'> A A
func7 safly
func8 <__main__.A object at 0x059B4750>

Process finished with exit code 0

我们看到a.func5(“safly”)这样的调用方式是错误的,其他的方式是可以的,这就为我们增加了调用方法的写法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值