day07_雷神_面向对象进阶

day07

1.接口类(抽象类)

接口类和抽象类是一种规范,写代码时的规范。

两个思想: 一个是统一接口,一个是定义规则。

最终版本:接口类,抽象类,是一种规范,写代码时的规范 强制性的规定。

from abc import ABCMeta,abstractmethod
class Payrole(metaclass=ABCMeta):  # 抽象类或者接口类,制定规范,统一方法名。
    @abstractmethod
    def pay(self): pass

class QQpay(Payrole):
    def pay(self,money):
        print(‘您已经通过qq支付了%s元‘ %money)

class Alipay(Payrole):
    def pay(self, money):
        print(‘您已经通过支付宝支付了%s元‘ % money)

class Wechatpay(Payrole):
    def pay(self, money):
        print(‘您已经通过支付宝支付了%s元‘ % money)

def pay(obj,money):
    obj.pay(money)

# a = QQpay()
# b = Alipay()
c = Wechatpay()
# pay(a,100)  # 归一化设计,统一你的支付方式
# pay(b,1200)
pay(c,10000)

2. 多态,鸭子类型

Python默认就支持多态,自带多态,也叫鸭子类型。

python 对于一些相似的方法,不用强制规定,都是约定俗成。

3. 封装

广义封装: 封装到对象中的属性(普通字段),静态字段等。

狭义封装: 私有性封装。

私有:包括私有静态字段(私有静态变量),私有普通字段(私有对象属性),私有方法。

3.1 私有静态字段

class Person:
    country = ‘China‘ # 公有静态字段(公有静态变量)
    __name = ‘oldboy‘ # 私有静态字段(私有静态变量)
    __age = 1000 # 私有静态字段(私有静态变量)
    def func1(self):
        return self.__name
print(Person.country)
在类的外部不能调用
print(Person.__name)
p1 = Person()

print(p1.__name)
print(Person.__dict__[‘_Person__name‘])
print(Person._Person__name)  虽然可以,但是一定不要这样访问。
在类的内部可以访问
print(p1.func1())

派生类也不可访问父类的私有静态字段。

class God:
    __kind = ‘黄种人‘  # _God__kind

class Person(God):
    country = ‘China‘ # 公有静态字段(公有静态变量)
    __name = ‘oldboy‘ # 私有静态字段(私有静态变量)
    __age = 1000 # 私有静态字段(私有静态变量)
    # def func1(self):
    #     return self.__name
    def func2(self):
        return self.__kind  # _Person__kind

p1 = Person()
print(p1.func2())

总结: 私有静态字段:类内部可以访问,父类以及类的外部不能访问。

只要类执行,将类的内容加载到内存时,发现有 __变量名 这样的Python解释器自动将__变量名转化成_类名__变量名

类执行,所有的字段和函数名(即内存地址)都会被加载。

3.2 私有普通字段

class Person:
    def __init__(self,name,age):
        self.name = name  # 公有普通字段 (公有普通对象属性)
        self.__age = age  # 私有普通字段 (私有普通对象属性)
    def func1(self):
        return self.__age
p1 = Person(‘alex‘, 40)
print(p1.name)
print(p1.func1())

私有成员用在哪里?

示例一: 密码加密

class Cipher_encryption:

    def __init__(self,username,password):
        self.username = username
        self.__password = self.__encryption(password)

    def __encryption(self,pwd):
        ‘‘‘
        加密处理
        :param pwd:
        :return:
        ‘‘‘
        return ‘%s hao123‘ % pwd

user1 = Cipher_encryption(‘alex‘, ‘alexsb‘)
print(user1.username)
# print(user1.password)
print(user1.__dict__)
对于只想让类内部使用的成员,要设置成私有成员。

示例二:

class A:
    a = 1
    b = 2
    def __init__(self):
        c = 666
a1 = A()
a1.a = 333
a1.b = 555
print(a1.a,a1.b,a1.c)

c = 666 不在a1对象的内存地址中,虽然执行了__init__方法,但是没有self.c = 666.

示例三: 类中遇到双下线加变量,就自动改名字。

class A:
    def __init__(self):
        self.__func()
    def __func(self):
        print("in A")

class B(A):
    def __func(self):
        print("in B")

b = B()
这时候输出的是A,因为__func函数改名字了。

4. 字段,方法,普通方法,静态方法,类方法,属性

4.1 普通方法

一般由对象调用。

4.2 属性

@property

class People:
    def __init__(self, name, weight, height):
        self.name=name
        self.__weight=weight
        self.__height=height

    @property
    def bmi(self):
        return self.__weight / self.__height**2

p1 = People(‘天‘, 95,1.83)
print(p1.bmi)
# property 属性将你的一些方法伪装成属性,虽然在代码上没有什么提高,让其看起来更合乎情理.

@ property 下的@方法.setter,修改

class Goods:

    def __init__(self,name,origin_price,discount):
        self.name = name
        self.__origin_price = origin_price
        self.__discount = discount

    @property
    def price(self):
        return self.__origin_price*self.__discount

    @price.setter
    def price(self,new_price):
        self.__origin_price = new_price

p1 = Goods(‘apple‘,5,0.8)
print(p1.price)
p1.price = 8
print(p1.price)

@ property 下的@方法.deleter,删除

class People:
    def __init__(self, name, age, sex):
        self.name = name
        self.__age = age
        self.__sex = sex

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self,new_age):
        if type(new_age) == int:
            self.__age = new_age
        else:
            print(‘请输入一个整数‘)

    @age.deleter
    def age(self):
        print(666)

p1 = People(‘天‘, 28, ‘男‘)
print(p1.name)
p1.name = ‘地‘
print(p1.name)
print(p1.age)  # p1.age 触发 @property装饰的方法
p1.age = ‘1234‘ # p1.age = ‘1234‘  触发 @age.setter装饰的方法
print(p1.age)
del p1.age  # del p1.age 触发  @age.deleter装饰的方法

4.3 类方法

一般是由类名调用.有些情况,对于类内部的方法,无需对象直接调用,而类名直接调用即可。

@classmethod

class Goods:

    __discount = 0.8

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

    @property
    def price(self):
        return self.__origin_price * Goods.__discount

    @classmethod
    def discount(cls,new_discount):
        Goods.__discount = new_discount

p1 = Goods(‘apple‘,5)
print(p1.price)
# p1.discount(0.85)
Goods.discount(0.85)
print(p1.price)

4.4 静态方法

不需要传入对象,和类名,直接调用即可.

class A:

    def __init__(self):
        pass

    @staticmethod
    def login(username,password):
        print(username,password)

A.login(‘alex‘,123)

5. 其他成员及方法

isinstance() 对象是否属于这个类,或者这个类血缘关系.

class C: pass
class A(C): pass
class B(A): pass

abj = B()
print(isinstance(abj,B))  #True
print(isinstance(abj,A))  #True
print(isinstance(abj,C))  #True

issubclass() 判断 第一类是第二个类的后代.True

class C: pass

class A: pass

class B(A,C): pass

print(issubclass(A,B)) #False
print(issubclass(B,C)) #True

反射:非常重要。~!~!

01.类中的反射:

这个方法是用dict方法,通过字典的key来查询。

class A:
    role = ‘Teacher‘

    def func(self):
        print(666)

msg = input(‘>>>‘)
print(A.role)
print(A.__dict__[msg])

getattr方法

getattr(A,msg)  # *****
getattr(A,msg)(111)  # 通过字符串 去到 类名 中获取对应的值.
print(getattr(A,msg))
hasattr() *****
print(hasattr(A,msg))
if hasattr(A,msg):
    print(getattr(A,msg))
else:
    print(‘不存在此值‘)

setattr() 增加或者修改 **
setattr(A,‘name‘,‘alex‘)
setattr(A,‘role‘,‘student‘)
print(A.__dict__)

delattr(A,‘role‘)  # 删除*
print(A.__dict__)

02.对象中的反射

在python 中一切皆对象,凡是通过 什么.什么 通过 反射都能取到

class A:
    role = ‘Teacher‘

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

a1 = A(‘太白‘, 18)

print(hasattr(a1,‘name‘))           True
print(hasattr(a1,‘sex‘))            False
print(getattr(a1, ‘role‘))          Teacher

03. 模块中

一个模块就是一个文件

import time

print(time.time())

print(getattr(time,‘time‘))

print(getattr(time,‘time‘)())

oldboy模块

def func():

name = ‘alexsb‘

print(‘此函数完成的是打印666功能‘)

class A:

role = ‘Teacher‘

def func1(self):

print(666)

反射示例:

import oldboy

print(getattr(oldboy,‘func‘))
getattr(oldboy,‘func‘)()
方式一
print(getattr(oldboy,‘A‘))
print(getattr(oldboy,‘A‘).role)
getattr(oldboy,‘A‘).func1(11)

方式二
print(getattr(getattr(oldboy,‘A‘),‘role‘))

04. 当前模块中

def login():
    print(666)

msg = input(‘>>>‘)
import sys

getattr(sys.modules[__name__],msg)()
print(globals())  #{‘__name__‘: ‘__main__‘, ‘__doc__‘: None, ‘__package__‘: None, ‘__loader__‘: <_frozen_importlib_external.SourceFileLoader object at 0x000001B465F3A3C8>, ‘__spec__‘: None, ‘__annotations__‘: {}, ‘__builtins__‘: <module ‘builtins‘ (built-in)>, ‘__file__‘: ‘C:/Users/Administrator/PycharmProjects/oldboy/day07/day07/07 其他成员及方法.py‘, ‘__cached__‘: None, ‘login‘: <function login at 0x000001B465E31E18>, ‘msg‘: ‘login‘, ‘sys‘: <module ‘sys‘ (built-in)>}

print(locals())
print(dir())  # [‘__annotations__‘, ‘__builtins__‘, ‘__cached__‘, ‘__doc__‘, ‘__file__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘login‘, ‘msg‘, ‘sys‘]

print(__name__)  #__main__

其他方法:

01. len

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)

a = A()
print(len(a))

02. hash

class A:
def __init__(self):
    self.a = 1
    self.b = 2

def __hash__(self):
    return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))

03. __ str__

类中如有__str__方法,print(对象),str(a) print(‘%s‘ % a),打印该对象时,默认输出该方法的返回值。

class A:
    def __init__(self):
        pass
    def __str__(self):
        return ‘太白‘
a = A()
print(a,type(a))  太白 <class ‘__main__.A‘>
print(str(a),type(str(a)))  太白 <class ‘str‘>
print(‘%s‘ % a)  太白

04. __ repr __

和str一样

class A:
    def __init__(self):
        pass
    def __repr__(self):
        return ‘太白‘
a = A()
print(a)
print(repr(a))
print(‘%r‘%a)

05. call

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:

    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print(‘__call__‘)

obj = Foo()  # 执行 __init__
obj()  # 执行 __call__

06. eq

07. __ del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

08. __ new__

实例化对象的时候自动触发。

单例模式:

class A:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = object.__new__(cls)
            cls.__instance = obj
        return cls.__instance

09. item系列

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

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        print(key,value)
        self.__dict__[key]=value
    def __delitem__(self, key):
        print(‘del obj[key]时,我执行‘)
    #     self.__dict__.pop(key)

f1 = Foo(‘sb‘)
# f1[‘name‘]  # 对对象进行字典式的查询操作 触发 __getitem__
# f1[‘age‘] = 18  # 对对象进行字典式的更改 触发 __setitem__
f1[‘age1‘]=19
# del f1.age1
del f1[‘age‘]  # 对对象进行字典式的del删除 触发 __delitem__
f1[‘name‘]=‘alex‘
print(f1.__dict__)

原文地址:https://www.cnblogs.com/houbinglei/p/9268845.html

时间: 2024-11-09 05:03:59

day07_雷神_面向对象进阶的相关文章

python基础_面向对象进阶

@property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作.如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问

day06_雷神_面向对象初识

day_06 递归函数 自己用自己.一般递归100多次,都没有解决的问题,放弃递归. count = 0 def func1(): global count count += 1 print(count) func1() func1() 默认递归深度:998 设置递归深度 import sys sys.setrecursionlimit(20000) count = 0 def func1(): global count count += 1 print(count) func1() func1

day05_雷神_函数进阶

#day05 1.迭代器 1.1可迭代对象 str,list,tuple,dict,set,range,文件句柄 等都是可迭代对象 第一种方法:在该对象中,含有__iter__方法的就是可迭代对象,遵循可迭代协议. print(dir(str)) dir() 打印出str对象的所有方法. print('__iter__' in dir(list)) 返回值: True 说明是可迭代对象 第二种方法: isinstance("123",Iterable) from collections

Python_基础_(面向对象进阶)

一,isinstance(obj,cls) issubclass(sub,super) isinstance(obj,cls) # 判断对象obj是否是cls的一个实例 class Test: pass t = Test() print(isinstance(t,Test)) # True issubclass(sub,super) # 判断类sub是否为类super的子类 class Test: pass class Sub(Test): pass print(issubclass(Sub,T

2Python全栈之路系列之面向对象进阶及类成员

Python全栈之路系列之面向对象进阶及类成员 再次了解多继承 先来一段代码 #!/usr/bin/env python # _*_ coding:utf-8 _*_ class A:     def bar(self):         print("BAR")         self.f1()          class B(A):     def f1(self):         print("B")          class C:     def 

八、面向对象进阶

面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程进行更为深入的了解. @property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建

Python之路【第八篇】:Python基础(24)——面向对象进阶

参考连接: Python 面向对象(初级篇) http://www.cnblogs.com/wupeiqi/p/4493506.html python 面向对象(进阶篇) http://www.cnblogs.com/wupeiqi/p/4493506.html python 面向对象及相关 http://www.cnblogs.com/wupeiqi/articles/5017742.html 面向对象进阶: 类成员之字段.方法.属性: 类成员修饰符: 类成员之特殊成员 1.类方法 普通的方法

Python【day7】:Python学习(面向对象进阶、反射、socket介绍)

面向对象进阶 1.类变量和实例变量 # 一.变量 # 变量包括:实例变量和类变量, # 他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, # 实例变量属于对象 # 类变量属于类 class Province(object): country = "中国" #类变量 def __init__(self, name): self.name = name # 实例变量 # 直接访问实例变量(实例名来调用) obj = Province('河北省') print(obj.na

Python面向对象进阶和socket网络编程-day08

写在前面 上课第八天,打卡: 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __init__(self,name): self.name=name p = Chinese('standby') # 实例化一个对象 print(p) # 打印这个对象 --- <__main__.Chinese object at 0x0000000000B3A978> - 示例2: >&g