python之路-Day8
抽象接口
class Alert(object):
'''报警基类'''
def send(self):
raise NotImplementedError
class MailAlert(Alert):
def send(self): #如果子类中没有创建相应的功能时,就会报错。
print('hello world')
m = MailAlert()
m.send()
raise实现自动报警功能
静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
class Dog(object):
def __init__(self ,name):
self.name = name
@staticmethod # 把eat方法变为静态方法
def eat(self):
print("%s is eating" % self.name)
d = Dog("ChenRonghua") d.eat()
上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了
输出结果:
Traceback (most recent call last):
File "D:/py_s15/练习/1111.py", line 9, in <module>
d.eat()
TypeError: eat() missing 1 required positional argument: 'self'
想让上面的代码可以正常工作有两种办法
1. 调用时主动传递实例本身给eat方法,即d.eat(d)
2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了
类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class Dog(object):
def __init__(self, name):
self.name = name
@classmethod
def eat(self):
print("%s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat()
输出结果:执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的
C:\Python35\python.exe D:/py_s15/练习/1111.py
Traceback (most recent call last):
File "D:/py_s15/练习/1111.py", line 8, in <module>
d.eat()
File "D:/py_s15/练习/1111.py", line 6, in eat
print("%s is eating" % self.name)
AttributeError: type object 'Dog' has no attribute 'name'
此时可以定义一个类变量,也叫name,看下执行效果
class Dog(object):
name = '我是变量'
def __init__(self, name):
self.name = name
@classmethod
def eat(self):
print("%s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat()
输出结果:我是变量 is eating
属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class Dog(object):
def __init__(self, name):
self.name = name
@property
def eat(self):
print(" %s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat()
输出结果:Traceback (most recent call last):
File "D:/py_s15/练习/1111.py", line 8, in <module>
d.eat()
TypeError: 'NoneType' object is not callable
调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了
class Dog(object):
def __init__(self, name):
self.name = name
@property
def eat(self):
print(" %s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat
好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过 定义 静态属性来实现的, 比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:
1. 连接航空公司API查询
2. 对查询结果进行解析
3. 返回结果给你的用户
因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以。
航班信息查询
class Flight(object):
def __init__(self,name):
self.flight_name = name def checking_status(self):
print('checking flight %s status' %self.flight_name)
return 0
@property
def flight_status(self):
status = self.checking_status()
if status == 0:
print("flight got canceled...")
elif status == 1:
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later")
f = Flight('CA980')
f.flight_status
那现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?试试吧
f.flight_status = 1
输出结果:AttributeError: can't set attribute
很显然,修改这个静态属性是不能这样改的,不过需要通过@proerty.setter装饰器再装饰一下,此时 你需要写一个新方法, 对这个flight_status进行更改。
class Flight(object):
def __init__(self,name):
self.flight_name = name def checking_status(self):
print('checking flight %s status' %self.flight_name)
return 0
@property
def flight_status(self):
status = self.checking_status()
if status == 0:
print("flight got canceled...")
elif status == 1:
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later")
@flight_status.setter #修改静态属性
def flight_status(self,status):
status_dic = {
0 : 'cancle',
1 : 'arrived',
2 : 'departuresd'
}
print('\033[31;1mHas changed the flight status to \033[0m',status_dic[status])
@flight_status.deleter #删除静态属性
def flight_status(self):
print("status got removed...")
f = Flight('CA980')
f.flight_status = 2
del f.flight_status
类的特殊成员方法
1.__doc__ 显示类的描述信息
print(Flight.__doc__) 类.__doc__
2.__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class Dog(object):
'''够累'''
def __init__(self):
print(1)
def __call__(self, *args, **kwargs):
print(args,kwargs)
def __getitem__(self, item):
print('get item ',item)
return 22 print(Dog.__doc__)
print(Dog.__module__)
print(Dog.__class__)
输出结果: 够累 __main__ <class 'type'>
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
6. __dict__ 查看类或对象中的所有成员
class Province:
country = 'China'
def __init__(self,name,count):
self.name = name
self.count = count
def func(self,*args,**kwargs):
print('fun')
print(Province.__dict__.items())
m = Province('hebei',100000)
print(m.__dict__)
输出结果:
获取类的成员 {'__module__': '__main__', 'func': <function Province.func at 0x00000039DB60C400>, 'country': 'China', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Province' objects>, '__dict__': <attribute '__dict__' of 'Province' objects>, '__init__': <function Province.__init__ at 0x00000039DB60C378>}
获取对象的成员 {'name': 'hebei', 'count': 100000}
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Foo: def __str__(self): return 'alex li' obj = Foo() print(obj)
输出结果:alex li
8.__getitem__、__setitem__、__delitem__ 用于索引操作,如字典。以上分别表示获取、设置、删除数据 9. __new__ \ __metaclass__
class Foo(object):
def __init__(self, name):
self.name = name
f = Foo("alex")
上述代码中,f是通过 Foo 类实例化的对象,其实,不仅 f是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:f对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
class Foo(object):
def __init__(self, name):
self.name = name
f = Foo("alex")
print(type(f))
print(type(Foo))
输出结果:<class '__main__.Foo'>
<class 'type'>
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
1.普通方法:
class Foo:
def func(self):
print('hello')
def func(self):
'hello wupeiqi' Foo = type('Foo', (object,), {'func': func})
#type第一个参数:类名 #type第二个参数:当前类的基类 #type第三个参数:类的成员
类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
# _*_coding:utf-8_*_ class MyType(type):
def __init__(self, child_cls, bases=None, dict=None):
print("--MyType init---", child_cls, bases, dict)
# super(MyType, self).__init__(child_cls, bases, dict) # def __new__(cls, *args, **kwargs):
# print("in mytype new:",cls,args,kwargs)
# type.__new__(cls)
def __call__(self, *args, **kwargs):
print("in mytype call:", self, args, kwargs)
obj = self.__new__(self, args, kwargs) self.__init__(obj, *args, **kwargs) class Foo(object, metaclass=MyType): # in python3
# __metaclass__ = MyType #in python2 def __init__(self, name):
self.name = name
print("Foo ---init__") def __new__(cls, *args, **kwargs):
print("Foo --new--")
return object.__new__(cls) def __call__(self, *args, **kwargs):
print("Foo --call--", args, kwargs) # 第一阶段:解释器从上到下执行代码创建Foo类
# 第二阶段:通过Foo类创建obj对象
obj = Foo("Alex")
# print(obj.name)
类的生成 调用 顺序依次是 __new__ --> __call__ --> __init__
反射
通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法(反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!)
WEB框架,路由系统 li = {}
getattr getattr()专门去某个地方获取其他内部的东西,可以使字符串的形式 以字符串的形式去某个对象中获取指定的属性
hasattr 判断获取的某个东西中是否有我们想要的东西,相当于容器 以字符串的形式判断某个对象中是否含有指定的属性。
setattr 以字符串的形式去[某个对象]中设定指定的属性
delattr 以字符串的形式去[某个对象]中删除指定的属性
以字符串的形式导入模块 __import__('time')
app.py
from controller import account
action = input('>>>>>:')
if(hasattr(account,action)):
func = getattr(account,action)
result = func()
else:
result = ''
print(result)
account.py
def login():
return '请输入密码' def logout():
return '跳回登陆页面'
异常处理 一、基本结构
try:
代码块
代码块
。。。
except Exception as e:
将错误信息写入日志
二、复杂结构
try:
...
...
...
except
....
else: (与expect相反)
...
finally (肯定执行)
...
三、异常对象
try:
代码块
代码块
。。。
except Exception as e: #(e是Exceotion的对象) python内部将错误信息封装到e中
将错误信息写入日志 (e中封装了当前触发的错误信息)
四、异常种类
Exception能将所有的异常捕获
。。。
其他:只能处理某一种情况,精确的定位问题
try:
代码块
代码块
。。。
except Exception as e:
将错误信息写入日志
其他错误类型继承Exception
五、主动触发异常
raise Exception('邮件发送失败')
六、断言(异常处理的简写) #不会做记录
告知别人,,这个条件必须满足,起到警示作用。
assert
七、自定义异常
class HaitaoError(Exception):
def __init__(self,message):
self.msg = message
super(HaitaoError, self).__init__(message)
try:
name = 'alex'
if name != 'haitao':
raise HaitaoError('you can not take my body')
except HaitaoError as e:
print(e,e.msg)
except Exception as e:
print(e,111111)
基本模版展示:
try:
int('asdasdwqqws')
li = ['','']
li[1000]
except IndexError as e:
pass
except ValueError as e:
pass
except Exception as e:
pass
else:
print('a')
finally:
print('hello world')
app.py
#account/login
#account/logout
#home/index
while True:
action = input('>>>>>:')
m,n = action.split('/')
try:
module = __import__('controller.%s'%m,fromlist=True)
if(hasattr(module,n)):
func = getattr(module,n)
result = func()
else:
result = ''
except Exception as e:
result = 500
print(result)
此例子,将动态倒入模块,异常处理,以及反射融合在一起。实例中所调用的模块,在上面的反射实例中有提到。
异常种类
常用到的异常种类:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的 写入具体的异常处理,只能具体处理某一种异常,当遇到其他类型的错误程序就会报异常,导致无法运行,所以还有万能异常处理。
Socket 编程
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket和file的区别:
- file模块是针对某个指定文件进行【打开】【读写】【关闭】
- socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】
更多功能
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
参数一:地址簇
socket.AF_INET IPv4(默认) socket.AF_INET6 IPv6
socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
参数二:类型
socket.SOCK_STREAM 流式socket , for TCP (默认) socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。 socket.SOCK_SEQPACKET 可靠的连续数据包服务
参数三:协议
0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
sk.bind(address)
s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
sk.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5 这个值不能无限大,因为要在内核中维护连接队列
sk.setblocking(bool)
是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
sk.accept()
接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP 客户的连接(阻塞式)等待连接的到来
sk.connect(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
sk.connect_ex(address)
同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061
sk.close()
关闭套接字
sk.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag])
与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
sk.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
sk.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。
sk.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
sk.settimeout(timeout)
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )
sk.getpeername()
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
sk.getsockname()
返回套接字自己的地址。通常是一个元组(ipaddr,port)
sk.fileno()
套接字的文件描述符
简单的socket交互
socket_server
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #生成一个socket实例
server.bind(('0.0.0.0',8000))
server.listen(5)
print('start to listen'.center(20,'-'))
while True:
conn,client_addr = server.accept() #accept会返回两个值,conn就是实际建立的连接,service相当于整个服务,想和某个连接的通信,只能是通过conn,每一个小连接时conn
print(conn,client_addr) while True:
data = conn.recv(1024) #收数据,本次消息要收多少内容 1024字节
print('recv from cli',data)
conn.send(b'got you msg') #socket发送必须是字节格式
socket_client
import socket
client = socket.socket()
client.connect(('localhost',8000))
while True:
msg = input('>>:').strip()
if len(msg) ==0:continue
client.send(msg.encode())
print('send',msg)
data = client.recv(1024)
print('receive from server:',data)
客户端与服务端交互
服务端
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',8000))
server.listen(5)
conn,client_addr = server.accept()
print(conn,client_addr) while True:
data = conn.recv(1024)
print('rece from cli:',data)
conn.send(b'got your msg')
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('localhost',8000)) while True:
msg = input('>>:').strip()
if len(msg) ==0:continue
client.send(msg.encode())
print('send',msg)
data = client.recv(1024)
print('receive from server:',data)
这样的结果就是当再有客户端请求时,可以建立连接,但是无法交互,客户端也会卡住,当我们断开第一个客户端是,服务端也会断开,所以,我们的需要在小循环断开后继续建立新的连接
服务端
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',8000))
server.listen(5)
while True:
conn,client_addr = server.accept()
print(conn,client_addr) while True:
try:
data = conn.recv(1024)
print('rece from cli:',data)
conn.send(b'got your msg')
except ConnectionResetError as e:
print(e)
break
这里断开是会报连接错误,只要把这个错误抓住就行了。(断开后就无法执行data = conn.reve(1024),所以会报错)
通过socket,实现ssh连接。
客户端(程序在linux环境)
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
import socket
import subprocess
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',8000))
server.listen(5)
while True:
conn,client_addr = server.accept()
print(conn,client_addr) while True:
try:
data = conn.recv(1024)
print('rece from cli:',data)
res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE)
conn.send(res.stdout.read())
except ConnectionResetError as e:
print(e)
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('192.168.1.198',8000)) while True:
msg = input('>>:').strip()
if len(msg) ==0:continue
client.send(msg.encode())
print('send',msg)
data = client.recv(1024)
print(data.decode())
socket发送信息的存在缓存中,如果满了就一起发送出去。
但是如果执行动态命令或者命令返回的结果很长,这样就不能一次给我们返回结果,或者是返回的结果不是我们想要的,那么,改如何去解决呢。
通过服务端去告知客户端要发送数据的长度,然后客户端通过自己能接受最大字符串进行循环接受,然后统一打印。
服务端
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
import socket
import subprocess
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',8000))
server.listen(5)
while True:
conn,client_addr = server.accept()
print(conn,client_addr) while True:
try:
data = conn.recv(1024)
print('rece from cli:',data)
res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE)
res1 = res.stdout.read()
conn.send(str(len(res1)).encode())
print('--res len:',len(res1))
conn.send(res1)
except ConnectionResetError as e:
print(e)
break
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('192.168.1.198',8000)) while True:
msg = input('>>:').strip()
if len(msg) ==0:continue
client.send(msg.encode())
print('send',msg)
data = client.recv(1024)
print('res:',data.decode())
total_size = int(data.decode())
#和总长度比较
received_size = 0
res2 = b''
while received_size < total_size:
d = client.recv(1024)
res2 += d
received_size += len(d) #+=len(d) 防止最后不够1024
print('---------rece done')
print(res2.decode())
python之路-Day8的更多相关文章
- Python之路,Day8 - Socket编程进阶
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- Python之路,Day8 - Python基础 面向对象高级进阶与socket基础
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- Python之路Day8
摘要: Socket编程 异常处理 线程.进程 1.socket编程 1.1 socket 三次握手,注意阻塞的应用. 1.2 socketserver(2.x写作:SocketServer) 实现多 ...
- Python之路
Python学习之路 第一天 Python之路,Day1 - Python基础1介绍.基本语法.流程控制 第一天作业第二天 Python之路,Day2 - Pytho ...
- Python之路【第一篇】python基础
一.python开发 1.开发: 1)高级语言:python .Java .PHP. C# Go ruby c++ ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- Python之路【第十九篇】:爬虫
Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
随机推荐
- [转载]给IT人员支招:如何跟业务部门谈需求分析?
一提跟业务人员做“需求分析”,许多IT人员立刻就头大了,要么不在同一个“频道”讲话,要么“变来变去,定不下来”.如何跟业务部门谈需求分析呢,我们带着这个问题,与聚冠因尚的咨询顾问杨春波展开了讨论. 1 ...
- Ubuntu1404 (2)
1.启动远程桌面 (1)设置桌面共享:usr->share->applications->桌面共享,勾选"允许查看桌面"和"允许控制桌面",& ...
- HTML5服务器推送消息的各种解决办法
摘要 在各种BS架构的应用程序中,往往都希望服务端能够主动地向客户端推送各种消息,以达到类似于邮件.消息.待办事项等通知. 往BS架构本身存在的问题就是,服务器一直采用的是一问一答的机制.这就意味着如 ...
- 实用的Portraiture滤镜磨皮教程
滤镜可以快速地进行人物皮肤美化处理,Portraiture滤镜可以将皮肤柔化,消除多余的斑点,在磨皮后复制细节保留较多的通道到图层面板,用高反差保留滤镜提取细节,再更改图层混合模式即可以得到漂亮的肤色 ...
- 介绍Unreal Engine 4中的接口(Interface)使用C++和蓝图
这个教程是从UE4 Wiki上整理而来. 在C++中直接使用Interface大家应该很熟悉.只是简单先定义一个个有虚函数的基类,然后在子类中实现相应的虚函数.像这样的虚函数的基类一般概念上叫接口.那 ...
- vs快捷键汇总
1.相关查找快捷键 Ctrl+F: 查找 Ctrl+Shift+F: 在文件中查找 F3: 查找下一个 Shift+F3: 查找上一个 Ctrl+H: 替换 Ctrl+Shift+H: 在文件中替换 ...
- Shuffling Machine和双向链表
1. 双向链表 https://github.com/BodhiXing/Data_Structure 2. Shuffling Machine https://pta.patest.cn/pta/t ...
- 《JavaScript高级程序设计》学习笔记(5)——面向对象编程
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 本节内容对应<JavaScript高级程序设计>的第六章内容. 1.面向对象(Object ...
- Asynchronous javascript and xml
关于Ajax,学习了原生的ajax和JQ的ajax,如今,它已是无处不在,首先,我们知道开发或者使用的软件分为c/s和b/s两种,分别是客户端/服务端和浏览器端/服务端. 前者的优点是响应速度快,但是 ...
- A quick introduction to HTML
w3c reference : https://www.w3.org/TR/2014/REC-html5-20141028/introduction.html#writing-secure-appli ...