day7-面向对象高级与socket编程

今日学习的内容

1.类与对象

2.对象之间的交互

3.类的继承

4.继承原理

5.组合

6.抽象类

7.多态与多态性

8.封装

9.特性

10.反射

11.面向对象的高级用法

12.socket编程

1.类与对象

面象对象编程解决了程序扩展性的问题。

类的第一个功能:实例化;

类的第二个功能: 属性引用(包括变量属性和函数属性)。

例如:定义1个类,实例化2个对象,并引用属性

class Garen:
    camp = "Demacia"
    def __init__(self,nickname,aggresivity,life_value):
        self.nickname = nickname
        self.aggrv = aggresivity
        self.life_value = life_value

    def attack(self):
        print("is attacking..")

g1 = Garen("盖伦",82,100)
g2 = Garen("盖伦2",82,200)

print(g1.nickname)
print(g1.aggrv)
print(g1.life_value)

print(Garen.attack)
print(g1.attack)

输出:
-----------------------------------------------------------------------------
盖伦
82
100
<function Garen.attack at 0x00000000021EBAE8>  # 通过类调用的函数,称为function
<bound method Garen.attack of <__main__.Garen object at 0x00000000021E9C88>> # 通过实例调用的函数,称为bound method

2.对象之间的交互

例如: 创建2个类,实例化2个对象

class Garen:
    camp = 'Demacia'
    def __init__(self,nickname,aggresivity,life_value):
        self.nickname = nickname
        self.aggrv = aggresivity
        self.life_value = life_value

    def attack(self,enemy):
        enemy.life_value -= self.aggrv

class Riven:
    camp = 'Noxus'
    def __init__(self,nickname,aggresivity,life_value):
        self.nickname = nickname
        self.aggrv = aggresivity
        self.life_value = life_value

    def attack(self,enemy):
        enemy.life_value -= self.aggrv


g1 = Garen("盖伦",82,100)
r1 = Riven("瑞文",50,200)

print("-----------------------------------------")
# g1 attack r1
print("r1的生命值: %s" % (r1.life_value))
g1.attack(r1)
print("r1被攻击后的生命值: %s" % (r1.life_value))

# r1 attack g1
print("g1的生命值: %s" % (g1.life_value))
r1.attack(g1)
print("g1被攻击后的生命值: %s" % (g1.life_value))

3.类的继承

继承可以重用代码。

如果需要创建的两个对象有相同的属性,也有不同的属性,可以先创建一个基类(包含共性),然后再创建两个类,从基类继承共性,对于不同的属性(方法)可以重写。

代码重用的写法:

class Hero:
    def __init__(self,nickname,aggresivity,life_value):
        self.nickname = nickname
        self.aggrv = aggresivity
        self.life_value = life_value

    def attack(self,enemy):
        print("is attacking...",self,enemy)
        enemy.life_value -= self.aggrv

class Garen(Hero):
    camp = "Demacia"
    def run(self):
        print("is running.....")

class Riven(Hero):
    camp="Noxus"

g1 = Garen("盖伦",82,100)
r1 = Riven("瑞文",50,200)

g1.run()
g1.attack(r1)

输出:
--------------------------------------------------
is running.....
is attacking... <__main__.Garen object at 0x0000000002759DD8> <__main__.Riven object at 0x0000000002759E10>

继承的写法:

class People:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def test(self):
        print("from People.test")

# 继承的第一种写法:
class Teacher(People):
    def __init__(self,name,age,gender,level):
        People.__init__(self,name,age,gender)
        self.level = level

# 继承的第二种写法:
class Teacher2(People):
    def __init__(self,name,age,gender,level):
        super().__init__(name,age,gender)
        self.level = level

t = Teacher("tomas",20,"female","senior")
print(t.level)

4.继承原理

关于类的继承:

经典类(python2默认):采用深度优先
新式类(python3默认):采用广度优先

例如:

class A:
    def test(self):
        print('from A')

class B(A):
    # def test(self):
    #     print('from B')
    pass
class C(A):
    # def test(self):
    #     print('from C')
    pass
class D(B):
    # def test(self):
    #     print('from D')
    pass
class E(C):
    # def test(self):
    #     print('from E')
    pass
class F(D,E):
    # def test(self):
    #     print('from F')
    pass

f1 = F()
f1.test()
print(F.mro())

输出:
from A
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

5.组合

例如:

class Teacher:
    def __init__(self,name,birth,course):
        self.name = name
        self.birth = birth
        self.course = course

class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

class Date:
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day

t = Teacher("tom",Date(1999,12,20),Course("python",11000,"8mon"))
print(t.birth.year)

输出:
-------------------------
1999

6.抽象类

父类定义功能(函数名),子类必须重写函数功能,抽像类不能实例化,只能用来继承。
import abc

class AllFile(metaclass=abc.ABCMeta):
    def test(self):
        print("for testing....")
    @abc.abstractmethod
    def read(self):
        pass

    @abc.abstractmethod
    def write(self):
        pass

class Text(AllFile):
    def read(self):
        print("text read")

    def write(self):
        print("text write")

t = Text()
t.read()
t.write()
t.test()

输出:
-----------------------
text read
text write
for testing....

7.多态与多态性

多态是指同一种事物的不同形态,如序列化类型包括字符串,列表,元组

s = "helllo world"
l = [1,2,3]
t = (1,2,3)

多态性的用法:
class Animal:
def talk(self):
pass

class People(Animal):
    def talk(self):
        print("say hello")

class Dog(Animal):
    def talk(self):
        print("wang wang....")

class Cat(Animal):
    def talk(self):
        print("miao miao....")

p1 = People()
d1 = Dog()
c1 = Cat()

def func(obj):
    obj.talk()

func(p1)
func(d1)
func(c1)

输出:
-----------------------------------------
say hello
wang wang....
miao miao....

8.封装

封装可以隐藏类的属性(包括变量和函数)。

用法:

class Foo:
    x = 1
    def __init__(self,name,money):
        self.name = name
        self.__money = money

    def getmoney(self):
        print(self.__money)
        self.__spam()                    # 在内部函中调用隐藏函数

    def __spam(self):                    # 定义隐藏函数
        print("from __spam.......")


f = Foo("tom",100)

# print(f.name)
# 定义类时以下画线开头的变量,会被隐藏:AttributeError: 'Foo' object has no attribute '__money'
# print(f.__money)

# 尽管类在定义时隐藏了__money,但是在内部的函数中是可以正常调用的。
# f.getmoney()

# 以字典形式打印类和对象的属性。
print(Foo.__dict__)
print(f.__dict__)

# 打印隐藏变量的方法
print(f._Foo__money)


# 在类定义之后,赋值时,以下划线开头的变量不会变形,可以直接引用。
f.__x = 10000
print(f.__x)

输出:
------------------------------------------
{'__module__': '__main__', 'x': 1, '__init__': <function Foo.__init__ at 0x00000000021CB8C8>, 'getmoney': <function Foo.getmoney at 0x00000000021CB950>, '_Foo__spam': <function Foo.__spam at 0x00000000021CB9D8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
{'name': 'tom', '_Foo__money': 100}
100
10000

9.特性

特性的用法一:

import math
class Circle:
    def __init__(self,radius):
        self.__radius = radius

    def area(self):
        return math.pi * self.__radius**2

    def perimeter(self):
        return math.pi * 2 * self.__radius

	# 普通函数的调用方式:
	c = Circle(10)
	print(c.area())
	print(c.perimeter())

	输出:
	----------------------------
	314.1592653589793
	62.83185307179586

	import math
	class Circle:
	    def __init__(self,radius):
	        self.__radius = radius
	
	    @property     # area = property(area)
	    def area(self):
	        return math.pi * self.__radius**2
	
	    @property     # perimeter=property(perimeter)
	    def perimeter(self):
	        return math.pi * 2 * self.__radius
	
	# property的调用方式:
	c = Circle(10)
	print(c.area)
	print(c.perimeter)


	输出:
	----------------------------
	314.1592653589793
	62.83185307179586

特性的用法二:

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

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self,value):
        if not isinstance(value,str):
            raise TypeError("value must be str")
        self.__name = value

    @name.deleter
    def name(self):
        print("deleting.............")
        raise AttributeError("error")    # 删除时会报这个错

a = A('tom')
print(a.name)

a.name = "Frank"
print(a.name)

输出:
----------------------
tom
Frank

10.反射

反射的用法一:hasattr

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

    def compute(self):
        print(self.name,self.age)

p1 = foo("xxx",20)
if hasattr(p1,"compute"):
    p1.compute()
else:
    print("no")

输出:
-------------------
xxx 20

反射的用法二:getattr

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

    def compute(self):
        print(self.name,self.age)

p1 = foo("xxx",20)
if hasattr(p1,"compute"):
    func = getattr(p1,"compute")
    print(func)
    func()

输出:
----------------------
<bound method foo.compute of <__main__.foo object at 0x00000000021C9CF8>>
xxx 20

反射的用法三:setattr

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

    def compute(self):
        print(self.name,self.age)

p1 = foo("xxx",20)
print("修改前: %s" % p1.name)
setattr(p1,'name',"yyy")
print("修改后: %s" % p1.name)

输出:
修改前: xxx
修改后: yyy

反射的用法四:delattr

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

    def compute(self):
        print(self.name,self.age)

p1 = foo("xxx",20)
p1.z = 100
print(p1.__dict__)
delattr(p1,"z")
print(p1.__dict__)

输出:
-----------------------
{'name': 'xxx', 'age': 20, 'z': 100}
{'name': 'xxx', 'age': 20}

11.面向对象的高级用法

"def _call_"的用法:

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

    def __call__(self, *args, **kwargs):
        print("now, it's callable!")

f = Foo("tesila")
f()

输出:
----------------------------
now, it's callable!

"def _getitem_" "def _setitem_" "def _delitem_"的用法:

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

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

    def __setitem__(self, key, value):
        print("setitem")
        self.__dict__[key] = value

    def __delitem__(self, key):
        print("del object:")
        self.__dict__.pop(key)

f = Foo("tomas")
print(f['name'])

f['age'] = 1000
print(f['age'])

del f['age']
print(f.__dict__)

输出:
-----------------------------------------
setitem
getitem {'name': 'wills', 'age': 1000}
1000
del object:
{'name': 'wills'}

12.socket编程

执行远程命令的服务器与客户端:

服务端:

import socket
import subprocess
import json
import struct
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

server.bind(("127.0.0.1",8080))

server.listen(5)
while True:
    conn,addr = server.accept()
    print("client:",addr)
    while True:
        try:
            cmd = conn.recv(1024)
            if not cmd: break
            print("from client msg: %s" %cmd)

            res = subprocess.Popen(cmd.decode("utf-8"),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE
                                   )

            err = res.stderr.read()
            if err:
                back_msg = err
            else:
                back_msg=res.stdout.read()
            print(type(back_msg))
            # 第一阶段:制作报头
            head_dict = {
                'data_size':len(back_msg)
            }
            head_json = json.dumps(head_dict)
            head_bytes = head_json.encode("utf-8")

            # 第二阶段:发送报头的长度
            conn.send(struct.pack('i',len(head_bytes)))

            # 第三阶段:发送报头
            conn.send(head_bytes)

            # 第四阶段: 发送真实数据
            conn.sendall(back_msg)

        except Exception:
            break
    conn.close()
server.close()

客户端:

import socket
import json
import struct

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8080))

while True:
    cmd = input("client> ").strip()
    if not cmd: continue
    client.send(cmd.encode("utf-8"))
    # 收取报头长度
    head = client.recv(4)
    head_size = struct.unpack('i',head)[0]

    # 收取报头
    head_bytes = client.recv(head_size)
    head_json = head_bytes.decode("utf-8")
    head_dict = json.loads(head_json)

    data_size = head_dict['data_size']

    # 收取真实数据
    recv_size = 0
    recv_bytes=b''
    while recv_size < data_size:
        res = client.recv(1024)
        recv_bytes += res
        recv_size += len(res)

    print(recv_bytes.decode('gbk'))
posted @ 2017-07-15 16:07  不露自威  阅读(176)  评论(0)    收藏  举报