2018년 6월 26일 화요일

Python lambda

# 구조적 프로그래밍 # 1. SRP - Single Responsibility Principle (한 함수는 하나의 책임/기능 만) # 2. OCP - Open Closed Principle (함수에 대해 기능 확장에는 열려 있고, 코드 변경은 막는다.
결국 OCP를 위해서는 변경되는 코드가 분리되어 파라미터로 전달 되어야 한다.

data = [10, 70, 100, 50]
data2 = [(50,40), (100,60), (70,40)]
data3 = [{'kor':50, 'eng': 40},
         {'kor':100, 'eng': 60},
         {'kor':70, 'eng': 40}]

# 숫자 리스트 max
def m_max(d):
    c = None    
    for i in d:
        if(c == None or c<i):
            c = i
    return c
print(m_max(data))

# 튜플 리스트 max
def m_max2(d):
    c = None    
    for i in d:
        if(c == None or c[0]<i[0]):
            c = i
    return c
print(m_max2(data2))

# dictionary 리스트 max
def m_max3(d):
    c = None    
    for i in d:
        if(c == None or c['eng']<i['eng']):
            c = i
    return c
print(m_max3(data3))

# 조건 검사 코드를 제외한 동일한 코드가 반복 구현 된다.
# 조건 검사 코드를 일급 함수로 변경 분리해 내서 간략화 할 수 있다.

def fn1(n):
    return n

def fn2(n):
    return n[0]

def fn3(n):
    return n['eng']

def m_max_ocp(d, key):
    c = None    
    for i in d:
        if(c == None or key(c)<key(i)):
            c = i
    return c

print(m_max_ocp(data, fn1))
print(m_max_ocp(data2, fn2))
print(m_max_ocp(data3, fn3))

# 조건 함수가 너무 많아지는 문제 때문에 익명 함수(lambda)를 사용한다.

def m_max_ocp(d, key):
    c = None    
    for i in d:
        if(c == None or key(c)<key(i)):
            c = i
    return c

print(m_max_ocp(data, lambda n : n))
print(m_max_ocp(data2, lambda n : n[0]))
print(m_max_ocp(data3, lambda n : n['eng']))

s = lambda a, b : a+b
print(s(10, 20))



# default 값으로도 제공 가능하다.

def m_max_ocp(d, key=lambda n:n):
    c = None    
    for i in d:
        if(c == None or key(c)<key(i)):
            c = i
    return c
print(m_max_ocp(data))
print(m_max_ocp(data2, lambda n : n[0]))
print(m_max_ocp(data3, lambda n : n['eng']))


내장 함수들도 동일하게 lambda를 사용.
data1 = [10, 70, 100, 50]
data2 = [(50,40), (100,60), (70,40)]
data3 = [{'kor':50, 'eng': 40},
         {'kor':100, 'eng': 60},
         {'kor':70, 'eng': 40}]

print(max(data1))
print(max(data2, key=lambda n:n[0]))
print(max(data3, key=lambda n:n['eng']))

f = filter(lambda n:n>40, data1)
print(f) # <filter object at 0x01E21B30> generator 임

for n in f:
    print(n)

def myfilter(key, dt) :
    return (n for n in dt if key(n)) # ()는 generator
f = myfilter(lambda n:n>40, data1)
print(f)
for n in f:
    print(n)

m = map(lambda n:n*2, data1) # 개별 데이터에 대해 연산 설정

print (list(m))

(내장 리스트로도 가능)




s = sorted(data1) # 새 객체 생성print(s)

# data1 자체 정렬은 data1.sort()
s = sorted(data1, reverse=True)

print(s)

s = sorted(data2, key=lambda n:n[1])
print(s)

s = sorted(data3, key=lambda n:n['eng'])
print(s)

s = sorted(data3, key=lambda n:n['kor'], reverse=True)
s = s[0:2] # 상위 2개 뽑아 냄.
print([n['kor'] for n in s ])


import  statistics

def mysum(key, dt):
    return sum([key(n) for n in dt])

s = sum(data1)
print(s)
s = sum([n[0] for n in data2])
print(s)

s = mysum(key=lambda n:n[0], dt = data2)
print(s)

s = sum([n['eng'] for n in data3])
print(s)

a = statistics.mean(data1)
print(a)

md = statistics.stdev(data1)
print(md)

a = statistics.mean([n['eng'] for n in data3])
print(a)

Python Class


생성자

class Test:
    def __init__(self):
        self.a = 0        self.b = 0
    def setData(self, x, y):
        self.a = x
        self.b = y
        print(id(self))

    def show(self):
        print(self.a, self.b)

obj = Test()
print(id(obj))
obj.setData(100,200)
obj.show()


소멸자






class Test:
    def __init__(self):
        self.a = 0
        self.b = 0

    def setData(self, x, y):
        self.a = x
        self.b = y
        print("setData", id(self))

    def show(self):
        print("show", self.a, self.b)

    def __del__(self):
        print("del")


t = Test()
t.setData(10, 20)
t.show()
s = t
del(t) # target memory object를 지우는게 아니다. 참조 변수만 지우는 것이다.
print("hello")


t = Test()
t = 100 # 기존 Test() target object는 ref count가 0이되어 삭제 된다.
다른 참조가 혹시 있으면 그 참조가 없어질 때까지 삭제되지 않는다.


클래스 변수나 static 함수는 반드시 클래스 이름을 붙여줘야 한다.

class Test:
    st = 10 # class 변수 # Instance 생성과 무관. py 파일 해석시 바로 메모리에 할당됨.   
    def __init__(self, x, y): # 인스턴스 함수       
        print("init")
        self.a = x  # 인스턴스 변수        
        self.b = y

    def setData(self, x, y):
        st = 10 # 이건 지역 변수다 !!!        
        Test.st = 10 # 이건 class 변수다 !!!        
        self.a = x
        self.b = y
        print("setData", id(self))

    def show(self):
        Test.sfn() # static 함수 호출 시
        print("show", self.a, self.b)

    def sfn(): # static 함수       
        print("sfn")


print (Test.st)
Test.st = 100
print (Test.st)
a = Test(10, 20)
Test.sfn()
a.show()




class My:
    count = 0    def __init__(self):
        My.count += 1
    def showCount():
        print(My.count)

o1 = My()
o2 = My()
o3 = My()
My.showCount()


static 메소드와 달리 class 메소스는 class이름을 첫번째 인자로 받는다.



Class 함수와 Static 함수는 다르다.
class Test:
    st = 10 # class 변수 # Instance 생성과 무관. py 파일 해석시 바로 메모리에 할당됨.
    def __new__(cls, *args, **kwargs):
        print("new call")
        return object.__new__(cls)
    def __init__(self): # 인스턴스 함수        print("init call")
        self.a = 0        self.b = 0
obj = Test()

# 모든 python 클래스는 object라는 클래스를 자식 클래스다.
# object.__new__(cls)가 실제 객체 생성하는 일을 함.
#1. obj = Test.__new__(Test)  # 실제 객체 메모리 잡는 과정
#2. obj.__init__(obj)
# not thread-safe solution



class MySingle:
    __instance = None    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def setData(self, x, y):
        self.x = x
        self.y = y


obj1 = MySingle()
obj2 = MySingle()
print(id(obj1), id(obj2))


상속

class People:

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

    def setName(self, name):
        self.name = name

class Student(People):

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


std = Student("홍", 20, 2323)
std.setName("이")

2018년 6월 25일 월요일

Python 내장 리스트와 Generator

* 내장 리스트 *
def devider(n):
   i = 1
   dv = [] 
   while(i <= n ): 
   if (n%i == 0): 
     dv.append(i) i += 1
     return dv 
 # 내장 리스트 방법 
def devider2(n): 
 return [d for d in range(1, n+1) if n%d == 0 ]
sal = [1000, 2000,3000, 4000, 5000]
net = [(n - (n * 0.033)) for n in sal]
print (net)
data = [(70, 60), (80, 40), (30,55)]
ft = [c[0] for c in data]
print(sum(ft))
st = [c[1] for c in data]
print(sum(st))
조건부 내장 리스트
if를 붙여서 조건을 추가할 수 있다.
sal = [1000, 2000,3000, 4000, 5000]
net = [(n - (n * 0.033)) for n in sal if n > 3000]
print (net)
* generator *
내장 리스트에 [] 대신 ()을 사용하면 generator가 생성 된다.
generator 사용 이유 : 메모리 절약.
내장 리스트는 생성 시 메모리를 모두 잡지만,
generator는 사용 시점에 값이 계산 되며 이전 계산 값은 기억하지 않는다.
import sys
내장 list 생성 방식
myLL = [n *10 for n in range(1,10000)] 
print(sys.getsizeof(myLL)) # range의 크기에 따라 메모리 증가 함.
generator 생성 방식
myGE = (n *10 for n in range(1,10000)) 
print(sys.getsizeof(myGE))
generator는 range의 크기에 따라 메모리 증가 하지 않음. 객체 메모리만 잡힐뿐 메모리에 담고 있지 않음.
때문에 bigdata 처리할 때 유용 함.
*Generator : 함수 기반 Generator와 내장 Generator*
함수기반 Generator
def fn() :
    yield 10    
yield 20   
yield 30    
yield 40
f = fn() # generator 객체
print(f)
print(next(f))
print(" ")
for i in f:
    print(i)
yield를 이용한 함수기반 Generator 객체는 내장 Generator에 비해 복잡한 연산의 결과를 Generator로 만들때 유용하다.
def divider(n):
    for i in range(1, n+1):
        if (n%i == 0):
            yield i
f = divider(10)
for n in f:
    print(n)
함수기반 Generator를 이용하여 세금 3.3을 제한 실수령액을 계산
def net(n):
    for i in n:
        yield i - i*0.033        
n = net(salary)
for i in n:
    print(i)
비교 : 동등한 결과를 내는 기존 내장 generator
result = (n - n*0.033 for n in salary)
d ={'name': 'son', 'kor':100, 'eng':80, 'name': 'kang', 'kor':80, 'eng':100} 
print([n for n in d.values() if type(n) == int])

2018년 6월 24일 일요일

Python Type 그리고 LGB 룰

Python은 Reference counted 메모리 관리.
is는 referenced object 주고가 같은지 비교.
==는 값을 비교.


-1은 True다. find는 찾지 못하면 -1을 리턴한다. find 보다는 in을 쓰는게 좋다.

f = filter(lambda n:'철' in n, data4)
for n in f:
    print(n)

False로 처리되는 애들은 아래와 같다.
False불리언거짓
NoneNone 유형값 없음
0정수0
0.0실수0
0j복소수0
''문자열빈 문자열
()튜플빈 튜플
[]리스트빈 리스트
{}집합빈 집합
dict()사전빈 사전

3항 연상 대신
rst = 100 if (a>0) else 200rst = (200, 100)[a>0]
rst = {True:100, False:200}



리스트 -> Dictionary
my = [13, 23, 33]
e = enumerate(my)
print( dict(e))
my1 = [12, 22, 32]
z = zip(my, my1) # key value list를 묶어서 dict 만들어 줌.print( dict(z))



리스트 항목 빈도 및 최빈도 추출
import collections
my = [10, 10, 10, 20, 20,30]
c = collections.Counter(my)
print (c)
print(c.most_common(3))


순서 있는 딕셔너리
o = collections.OrderedDict()
o['zz'] = 1o['bb'] = 20print (o)


Deque
q = collections.deque(maxlen=3)
q.append(10)
q.append(20)
q.append(30)
print (q)
q.append(40)
print(q)
q.appendleft(90)


배열
import array

arr = array.array('i')
arr.append(10)
arr.append(20)
arr.append(30)
print(arr)

arr.append(139065539)

print (arr)

함수 가변 파라미터
# 튜플을 가변인자로 넘길 때는 *를 붙여준다. 받는 쪽에서는 tuple로 받는다.




def fb4(*ar) :
    for a in ar:
        print(a)

fb4(10 ,20 , 30)
fb4("aa", "bb")

# 정의되지 않은 인자를 받고자 하면 **를 붙여준다. 받는 쪽에서는 dictionary로 받는다.




def fn5(**args): # 정의 되지 않은 인자    print(args)

fn5(a=10, b=20, c=30)
fn5(name="홍길동", age=20)


{'a': 10, 'b': 20, 'c': 30}
{'name': '홍길동', 'age': 20}





d = {'name': "이순신", 'age':40}
s = '%(name)s %(age)d' % data


def fn6(**args):
    print(args)
    
fn6(**d) # 정의 되지 않은 인자로 dictionary를 넘길 때는 **를 붙여 준다.

print('{name} {age}'.format(**data)



a = 10
b = 3.14
c = 'abc'
s = 'b {1} a {0} c{2}'.format(a, b, c)
# 아래와 동치. 가변인자로 튜플 넘길 때는 * 붙여 준다.
s = 'b {1} a {0} c{2}'.format(*(a, b, c))
print(s)


문자열 가운데 정렬
print("acb".center(30))

포멧에 정의되지 않은 인자를 주는 방식
s = '{aa}, {bb} {cc}'.format(aa =10, bb=20, cc=30)
print(s)






# LGB Rule. 변수 찾기 우선 순위 : Local Global Built-ing = 10     # 글로벌 변수 임.
def fn():
    g = 100 # 로컬 변수 임.    print(locals())
    print(id(g))

fn()
print(globals()) # 전역 변수 목록print('g=', g)
print(id(g))




str = 'korea'
n = str(n) # error. Global str이 Builtin str보다 우선 순위가 높아서 에러 발생.


# 글로벌 변수를 로컬에서 사용하는 방법
g = 10
def fn():
    global g
    g = 100
fn()
print(g) # 100 출력. global g 때문에 로컬에서도 global 변수 사용

def fn():
    my = [10, 20, 30] # 리스트는 stack이 아닌 heap에 생성됨.    print(id(my))
    return my

rst = fn()
print(rst, id(rst))

4859544[10, 20, 30] 4859544



switch 대치
def fn1():
   print("fn1")

def fn2():
    print('fn2')

menu = {1:fn1, 2:fn2}
menu[1]()

dictionary에 get을 사용하면 default 값을 정해줄 수 있다.

d = {10:"A", 9:"A", 8:"B", 7:"C", 6:"D"}
print (d.get(n//10, "F"))




Tuple은 ()로 만든다.
다만, (10)과 같이 1항은 그대로는 숫자다.
때문에 (10,)와 같이 ,를 추가해줘야 한다.


2018년 6월 19일 화요일

AIA Certificate Test

http://10.196.89.74/country/country_philippines.php
https://www.accuweather.com/en/al/tirana/6522/current-weather/6522?lang=en-us

https://tv.sohu.com/20180705/n600562967.shtml

http://www.nbcnews.com/id/21134540/vp/45025092

openssl s_client -connect css.tv.itc.cn:443 -showcerts -servername css.tv.itc.cn

CONNECTED(00000003)
depth=0 C = CN, ST = beijing, L = beijing, O = Beijing Sohu New Media Information Technology Co. Ltd, OU = Tech, CN = tv.sohu.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = CN, ST = beijing, L = beijing, O = Beijing Sohu New Media Information Technology Co. Ltd, OU = Tech, CN = tv.sohu.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/C=CN/ST=beijing/L=beijing/O=Beijing Sohu New Media Information Technology Co. Ltd/OU=Tech/CN=tv.sohu.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
-----BEGIN CERTIFICATE-----
MIIMajCCC1KgAwIBAgIQDVf17iSUp5uNqa5Mgv02FDANBgkqhkiG9w0BAQsFADBe
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMR0wGwYDVQQDExRHZW9UcnVzdCBSU0EgQ0EgMjAxODAe
Fw0xODA2MjcwMDAwMDBaFw0xOTA3MjcxMjAwMDBaMIGWMQswCQYDVQQGEwJDTjEQ
MA4GA1UECBMHYmVpamluZzEQMA4GA1UEBxMHYmVpamluZzE+MDwGA1UEChM1QmVp
amluZyBTb2h1IE5ldyBNZWRpYSBJbmZvcm1hdGlvbiBUZWNobm9sb2d5IENvLiBM
dGQxDTALBgNVBAsTBFRlY2gxFDASBgNVBAMTC3R2LnNvaHUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApR6Jxf/ydI1vcMSnAdKaOXI8O+SVzbxU
h7BQI9lXzih4Ofa15T+QuWNDhBdUejabulgY0Biw6Y8kSUQt+9f0BeGNWoJ7b28K
X15VhcbA80Ld5ydoGQICG3p84JR+/P3cTM+OEA2UpFQSP9PkV/RxnmxrnkCM1DFr
l2psRL2RoFf+xKEVvrH+KOcQBdIZjjt5uJQnebQ0oLCPgrPTkKe5S5WLtx2baVZM
hKGgP+ItTE4ku6LV7T9mDx68dX7w5Sp88TqMFnsOYXGyzWZ4zALq8eWRR/U7NnHD
MQfZ7VI4y+M9theTH/tE3nAEOypjjY9DYI1vSUNg/97oOtHc4SDW8QIDAQABo4II
6TCCCOUwHwYDVR0jBBgwFoAUkFj/sJx1qFFUd7Ht8qNDFjiebMUwHQYDVR0OBBYE
FGpeb5Y/B+alEVvBxiqhzFssrS+QMIIGWgYDVR0RBIIGUTCCBk2CC3R2LnNvaHUu
Y29tghoqLmNsdWIubXVzaWMueXVsZS5zb2h1LmNvbYIPKi5hcGkudHYuaXRjLmNu
ghMqLnN0b3JlLnR2LnNvaHUuY29tghQqLmh1d2lmaS5oZC5zb2h1LmNvbYIQcGF5
LnNtcy5zb2h1LmNvbYIQKi5zby50di5zb2h1LmNvbYIRKi5jZG4udHYuc29odS5j
b22CEiouZ2FtZS50di5zb2h1LmNvbYIQKi5oZC50di5zb2h1LmNvbYINKi5wcC5z
b2h1LmNvbYIScDEuYmFpLnNvaHUuY29tLmNughMqLmFwcC55dWxlLnNvaHUuY29t
ghAqLnVwLmhkLnNvaHUuY29tgg8qLmZpbG0uc29odS5jb22CEnJjLmFwcC50di5z
b2h1LmNvbYISKi5saXZlLnR2LnNvaHUuY29tghB0di5ibG9nLnNvaHUuY29tghEq
Lm90dC5oZC5zb2h1LmNvbYIRKi52cnMudHYuc29odS5jb22CECoubWIuaGQuc29o
dS5jb22CEGltZy5tbXMuc29odS5jb22CFCouaW1nLnBwLnNvaHUuY29tLmNughJw
Mi5iYWkuc29odS5jb20uY26CEyouZGFubXUudHYuc29odS5jb22CECouaGQuc29o
dS5jb20uY26CGCouYXBpLmh1d2lmaS5oZC5zb2h1LmNvbYIWKi5jbHViLnYueXVs
ZS5zb2h1LmNvbYIUKi5sYXVuY2guaGQuc29odS5jb22CEiouY2hhdC50di5zb2h1
LmNvbYIRKi52b2QudHYuc29odS5jb22CDiouanMudHYuaXRjLmNugg0qLnR2LnNv
aHUuY29tgg8qLnZvZC50di5pdGMuY26CFmZsYXNoLnl1bGUuc29odS5jb20uY26C
FSoubXVzaWMueXVsZS5zb2h1LmNvbYIRKi52Lnl1bGUuc29odS5jb22CFCouY2x1
Yi55dWxlLnNvaHUuY29tghEqLmF0eS50di5zb2h1LmNvbYIRKi5wMnAuaGQuc29o
dS5jb22CFXQxLmNvb3AuZmlsbS5zb2h1LmNvbYIYKi5jb21tZW50Mi55dWxlLnNv
aHUuY29tgg0qLmhkLnNvaHUuY29tghAqLm15LmhkLnNvaHUuY29tghMqLm15LnR2
LnNvaHUuY29tLmNughYqLnN0YXQub3R0LmhkLnNvaHUuY29tghIqLnN2Y3MuaGQu
c29odS5jb22CEioub3Blbi50di5zb2h1LmNvbYIPKi55dWxlLnNvaHUuY29tghgq
LmFwaS5sYXVuY2guaGQuc29odS5jb22CDm0uaXBjLnNvaHUuY29tghEqLnZpcC50
di5zb2h1LmNvbYIMKi5kLnNvaHUuY29tghAqLmRjLnR2LnNvaHUuY29tghEqLm90
dC50di5zb2h1LmNvbYIOKi52cnMuc29odS5jb22CECoubGl2ZS50di5pdGMuY26C
ECoucHAuc29odS5jb20uY26CECouc3RvcmUuc29odS5jb22CEnQxLm0uZmlsbS5z
b2h1LmNvbYIPZGF0YS52b2QuaXRjLmNughQqLmNsaWVudC5oZC5zb2h1LmNvbYIU
Ki5zaG93Lnl1bGUuc29odS5jb22CEiouY2x1Yi50di5zb2h1LmNvbYISKi5pZm94
LmhkLnNvaHUuY29tghQqLmltZy5wdS5zb2h1LmNvbS5jboIXKi5yZWRpcy5hcGku
dHYuc29odS5jb22CEmYxLnNwb3J0cy5zb2h1LmNvbYIQKi5kbS5oZC5zb2h1LmNv
bYILKi50di5pdGMuY26CESoubmF0LnR2LnNvaHUuY29tghMqLnBob3RvLnBwLnNv
aHUuY29tggsqLmg1Lml0Yy5jboIRKi5ib3gudHYuc29odS5jb22CFHQyLmFwaS5m
aWxtLnNvaHUuY29tghAqLmRsLmhkLnNvaHUuY29tghAqLmxtLnR2LnNvaHUuY29t
ghAqLnlpLnR2LnNvaHUuY29tghcqLmNvbW1lbnQueXVsZS5zb2h1LmNvbYIPKi5p
bWcudHYuaXRjLmNugg8qLm0udHYuc29odS5jb22CEmltZy5iYWJ5LjU2Lml0Yy5j
boIQKi5teS50di5zb2h1LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
KwYBBQUHAwEGCCsGAQUFBwMCMD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly9jZHAx
LmRpZ2ljZXJ0LmNvbS9HZW9UcnVzdFJTQUNBMjAxOC5jcmwwTAYDVR0gBEUwQzA3
BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu
Y29tL0NQUzAIBgZngQwBAgIwdAYIKwYBBQUHAQEEaDBmMCUGCCsGAQUFBzABhhlo
dHRwOi8vb2NzcDEuZGlnaWNlcnQuY29tMD0GCCsGAQUFBzAChjFodHRwOi8vY2Fj
ZXJ0cy5nZW90cnVzdC5jb20vR2VvVHJ1c3RSU0FDQTIwMTguY3J0MAkGA1UdEwQC
MAAwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdQCkuQmQtBhYFIe7E6LMZ3AKPDWY
BPkb37jjd80OyA3cEAAAAWQ/JoxbAAAEAwBGMEQCIBPiD2T5RjFRTTdqAVmI5ti0
ZNE6jVX3KQvs8mmI4RFIAiAfcoezTJzLvAxErQOTpa3sQRVp0bc23y99IEbZDaVB
jwB3AId1v+dZfPiMQ5lfvfNu/1aNR1Y2/0q1YMG06v9eoIMPAAABZD8mjTwAAAQD
AEgwRgIhAOreR+mPGQxYPHpKz43Ruakr49jk0aZzCCL9U24aL6ysAiEA0rOI08gv
1y73wT0T8hUntKyNGZU8bzX+pl69wAyXX2cwDQYJKoZIhvcNAQELBQADggEBAKhj
Ou8lx7OXnebrEmWjhlfzM51XAj6pnKrdYfPQdB0wYl9OaDRLN1NenTHFzG0w5ios
l9v+3gByccSyAevNQeWfUb03Jf2sc/OfkeauOGBsnr8QUUnb3Mp1h/ZEZM7aR8FS
CDKbxzH/TgC/nlCBsWxHexT/h/pGDsLTOID2NhRtmkMKa0QGVaTOYNX/dI/Sk8Zn
0aVx84pkVq+Ae2mm7WqvHjiBdobbZhe/wXn03bWoTjYF4exxchIoWipirG30ULS7
CBywW0EDFlRMgKe3Z9F5hPhQHjwSponx3IEtz7e+ovyR34uDaq7zSKHNWZAjDL8n
4KIuOR1ky/n8uHtglWQ=
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=beijing/L=beijing/O=Beijing Sohu New Media Information Technology Co. Ltd/OU=Tech/CN=tv.sohu.com
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3868 bytes and written 455 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 03FCEE6AB2874C326BED01113BFD7442195EEA0D0641B23E0EBD492A9244F549
    Session-ID-ctx:
    Master-Key: 74B9C13FFF8873CDA0B4824C2640AB834D781CA14628E9F3D72CEC3FBFC14FFDFCA26D6FC32F2B7B2C6F3282B27E28AA
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 46 db ef 17 7b 5c dd d7-b2 cd b3 69 0f b1 03 de   F...{\.....i....
    0010 - 05 85 0a a1 82 7c e0 89-47 bc c2 ec df 56 80 32   .....|..G....V.2
    0020 - cd 0d a0 77 13 1f 3a fb-41 70 24 ce 73 dd e9 8a   ...w..:.Ap$.s...
    0030 - c2 bf a5 65 16 7e af a1-14 0d 70 18 32 1a 88 cf   ...e.~....p.2...
    0040 - 95 99 2e ed f4 a2 48 f0-43 78 3d 04 41 df 2e d6   ......H.Cx=.A...
    0050 - e2 61 11 18 e4 6a 01 57-d4 8a ae 43 63 06 84 07   .a...j.W...Cc...
    0060 - 53 f1 1b ba e3 36 e7 d9-44 b0 f7 9c fd db 70 d3   S....6..D.....p.
    0070 - df 07 a2 6b e7 b3 e1 e8-93 77 16 27 5c fd a3 a0   ...k.....w.'\...
    0080 - 0f 0f 4e 52 91 fe f3 12-e4 e5 d8 a7 b3 13 de 5f   ..NR..........._
    0090 - b5 78 43 98 63 78 2d b2-24 b9 31 2e b1 f9 be cf   .xC.cx-.$.1.....
    00a0 - 0a 73 8c d9 dd c3 1f 70-24 51 6f 45 4e b6 54 01   .s.....p$QoEN.T.
    00b0 - 7a 61 51 4d 7b fb e9 51-a6 e7 32 c5 e3 03 d4 9f   zaQM{..Q..2.....

    Start Time: 1531100548
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---