반응형
Basic
void main() 
{
  // study0 : variable 
  var name = 'Yoon Engineer';
  print("Hello ${name}");  
  
  // study1 : Operator
  int number1 = 10;
  int number2 = 20;
  print('${number1} + ${number2} = ${number1+number2}');
  
  // study2 : Boolean and type check
  bool isTrue = true;
  bool isFalse = false;
  
  print(isTrue.runtimeType);
  print(isFalse);
  
  // study3 : String operator
  String name1 = 'Hello';
  String name2 = 'Yoon';
  
  print(name1 + ' ' +name2);
  print('$name1 $name2');
  
  // study4 : Dynamic vs Var
  dynamic dynamic_test = 'Yoon Engineer';
  print(dynamic_test.runtimeType);
  
  dynamic_test = 1;
  print(dynamic_test.runtimeType);
  
  // study5 : Null
  // nullable - null이 될 수 있음.
  // non-nullable - null이 될 수 없음.
  String null_test = 'Yoon';
  print(null_test);
  
  //null_test = null; // 오류
  String? null_test2 = 'Yoon';
  print(null_test.runtimeType);
  null_test2 = null;
  print(null_test.runtimeType);
}

 

Final vs Const
void main()
{
  // final : 값 변경 불가
  final String name = 'Yoon';
  
  print(name);
  
  // const : 값 변경 불가
  const String name2 = 'Yoon';
  print(name2);
  
  // final, const var을 따로 작성하지 않아도 됨.
  final name3 = 'Yoon';
  const name4 = 'Yoon';
  print(name3);
  print(name4);
  
  // final vs const
  // final은 빌드 타임 값을 몰라도 됨.
  // const는 빌드 타임 값을 알아야 함.
  final DateTime now = DateTime.now();
  
  //const DateTime now = DateTime.now(); // error
  
}

 

Null, Operator
void main()
{
  dynamic? number = null;
  
  print(null);
  // ?? 연산자 : 변수가 null이면 Rvalue로 변환함
  number ??= 4;
  print(number);
  
}
void main()
{
  int number = 1;
  
  print(number is int);
  print(number is String);
  print(number is double);
  
  print(number is! int);
  print(number is! String);
  print(number is! double);
  
  // Conditional operator
  bool result1 = 12 > 10 && 1 > 0;
  bool result2 = 12 > 10 || 0 > 1;
  print(result1);
  print(result2);
}

 

List, Map, Set
void main()
{
  // python list와 동일한 역할을 함
  List<String> blackPink = ['제니', '지수', '로제', '리사'];
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // List length
  print(blackPink.length);
  // Python 처럼 -1과 같은 인덱싱은 안됨
  print(blackPink[0]);
  // List value remove
  blackPink.remove('리사');
  print(blackPink);
  // List value add
  blackPink.add('리사');
  print(blackPink);
  // List indexOf
  print(blackPink.indexOf('리사'));
}
void main()
{
  // Map : {key : value}
  // Python dictionary와 똑같은 역할을 함.
  Map<String, String> dictionary = 
  {
    'Harry Potter' : '해리포터',
    'Ron weasley' : '론 위즐리'
  };
  print(dictionary);
  
  // addall
  dictionary.addAll(
    {
      'Hermione Granger' : '헤르미온느 그레인저'
    });
  print(dictionary);
  dictionary['Hello'] = "안녕";
  
  // indexing
  print(dictionary);
  print(dictionary['Harry Potter']);
  
  // remove
  dictionary.remove('Hello');
  print(dictionary);
  
  // keys, values
  print(dictionary.keys);
  print(dictionary.values);
}

 

If, switch
void main()
{
  int number = 3;
  if (number % 3 == 0)
  {
    print("ha");
  }
  else if(number % 3 == 1)
  {
    print("haha");
  }
  else
  {
    print("hahaha");
  }
  switch(number % 3)
  {
    case 0:
      print('ha');
      break;
    case 1:
      print('haha');
      break;
    default:
      print('hahaha');
      break;
  }
}

 

For loop
void main()
{
  int total = 0;
  List<int> numbers = [0, 1, 2, 3, 4, 5, 6];
  
  for(int n in numbers)
  {
    print(n);
  }
  
  print("----------------------");
  
  for(int n in numbers)
  {
    if(n == 3) continue;
    if(n == 5) break;
    print(n);
  }
}

 

Function, Signature
void main()
{
  var result1 = addNumbers(a:1, b:2);
  print(result1);
  
  var result2 = addNumbers(a:1, b:2, c:3);
  print(result2);
}

// named parameter
String addNumbers({
  required int a, 
  required int b, 
  int c =20})
{
  print('${a+b+c}');
  
  return 'success';
}
void main()
{
  int result = calculate(1, 2, 3, add);
  print(result);
}
 
// signature
typedef Operation = int Function(int x, int y, int z);

// 덧셈
int add(int x, int y, int z) => x + y + z;

// 뺄셈
int subract(int x, int y, int z) => x - y - z;

// function
int calculate(int x, int y, int z, Operation operation)
{
  return operation(x, y, z);
}

하루 정도 시간 내어 flutter를 하기 전에 Dart 언어를 쫙 읊어 보는 시간을 가져 본다.

Dart 언어는 공부해 보니 Java와 유사함을 느낌.

1. Var과 Dynamic : var는 한 번 타입이 정해지면, 변경 불가능. Dynamic은 한 번 타입이 정해지더라도 변경 가능.

2. Flutter2.0부터는 Null에 관련된 이슈가 업데이트됐다고 한다. 공부할 필요가 있을 것 같음.

3. final, const의 차이는 빌드 타임이다. final은 빌드 타임을 몰라도 되고, const는 알아야 함.

4. ??연산자는 null이면 Rvalue로 변환함.

5. 조건 연산자, 비트 연산자는 C와 동일함. 하지만 Dart 언어로 펌웨어 코딩할 일이 없으므로 비트 연산자는 사용되지 않을 것 같음.

6. List, Map, Set 모두 java와 일치함.

7. for 문도 java와 일치함. 결국 항상 느끼지만 새로운 언어를 공부할 때, 한 가지라도 제대로 터놓으면 다른 언어는 공부하기 편하다는 것을 뼈저리게 느낌.

아직까지 이상무.

728x90
반응형

'Flutter > Dart' 카테고리의 다른 글

Dart Study #2 클래스, 상속  (0) 2022.08.04
Dart Study #3 futures, async, await  (0) 2022.07.23
반응형

나는 라즈베리파이로 많은 프로젝트를 했다. 개인적으로 많이 가지고 놀기도 했고 특히 미니 해서 좋아했다. 위 사진은 내가 지금 가지고 있는 라즈베리파이들이다. 더 있지만 깔끔하게 관리되고 있는 것들로 사진을 찍었다.

그러다 보니 관련 문서도 자주 찾아보게 되고, Reddit에서 재밌는 프로젝트도 찾아보곤 한다.

많은 사람들이 balenaEtcher 프로그램을 이용해서 SD카드에 라즈비안을 굽는다. 나 또한 그랬다.

하지만 요즘엔 Raspberry Pi imager를 이용한다.


 
Raspberry Pi imager를 사용하는 이유.
  • 첫 번째 : balenaEtcher를 이용하면 라즈비안 OS도 별도로 설치해야 한다. 하지만 Raspberry Pi imager를 사용하면 별도의 OS 없이 라즈비안을 SD카드에 설치할 수 있다.
  • 두 번째 : 라즈비안 OS 설정을 Raspberry Pi imager에서 바로 설정할 수 있다.

나는 두 번째 이유 때문에 Raspberry Pi imager를 사용한다.

보통 처음 라즈베리파이를 사용하는 사람은 Full OS(GUI 포함)를 사용한다. 하지만 조금 사용하다 보면, 100에 99는 LITE OS를 설치하여 SSH로 접속한다.

SSH 접속하는 방법은 간단하다. 다만, 매번 설정하는 것이 귀찮다.


Raspberry Pi SSH 설정 (SD 카드 Flash 성공했다는 가정 하에)
  • SSH enable : ssh (확장자명 없이 빈 파일 생성)
  • WiFi 설정 : wpa_supplicant.conf (파일 생성) WiFi 5GHz 대신 2.4GHz 지향
  • Port fowarding : 기본 SSH 포트 번호 => 22
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
network={
    ssid="{WiFi 아이디}"
    psk="{WiFi 비밀번호}"
    key_mgmt=WPA-PSK
}

대부분 사람들이 위 방법으로 SSH를 설정한다. 하지만 이것도 한두 번이지 굉장히 귀찮은 작업이다. 이제 내가 추천하는 방법이다. 바로 Raspberry Pi imager를 이용하는 방법이다. 파일을 생성하고, 코드를 작성할 필요도 없다. 모두 GUI 선에서 해결할 수 있다.


추천 :Raspberry Pi imager를 이용하여 Raspberry Pi SSH 설정
  • Raspberry Pi imager 설치 (공식 홈페이지)

- 설치가 완료되면 아래와 같이 프로그램을 실행한다.

  • Advanced options (Ctrl + Shift + X)

- 컨트롤, 시프트, X 키를 동시에 누르면, 기본 옵션을 설정할 수 있는 창이 아래와 같이 보인다.

- 이 설정값을 매번 사용하고 싶으면 [for this session only][to always use]로 변경한다.

- set hostname : host name이다. 디폴트는 raspberrypi이다. 굳이 변경하지 않아도 된다.

- Enable SSH : SSH 활성화, 활성화하려면, 체크하면 된다. 초기 비밀번호를 변경할 수 있다. default는 raspberry이다.

- Configure wifi : 연결하고 싶은 WiFi 이름과 비밀번호를 입력한다. 단, 5GHz WiFi는 안된다. 항상 2.4GHz WiFi를 선택해야 한다.

위 GUI 방식으로 WiFi와 SSH를 설정하면, 실수도 줄어들고 빠르고 직관적으로 내 라즈베리파이를 설정할 수 있다. 지금까지 SD카드에 일일이 설정했다면, 이제 Raspberry Pi imager를 사용하길 바란다.

728x90
반응형
반응형

파이썬을 누구보다 좋아하고 애용하는 사람이지만 파이썬이 최고의 언어가 될 수 없는 10가지 이유를 이야기해보려 한다. 하지만 치명적인 10가지 단점이 있음에도 불구하고 전 세계 널리 사용되는 걸 보면 대단한 언어임에 틀림없다.

1. Indentation 

주의할 점은 Python에서는 Indentation이 선택사항이 아니라는 것이다. 이는 If문, for문 사용 시 문제를 일으킨다. 또한 함수가 어디에서 끝나는지 잘 보이지 않는다. 

2. Multiple version

Python에는 Python 2와 Python 3의 두 가지 버전이 있다.대부분의 경우 Linux에서 서로 나란히 설치되어 있기 때문에 많은 Linux distribution에서 Python 3으로 변환하는 데 시간이 걸리므로 두 가지 버전의 Python이 포함되어 출하된다. 

3. 런타임 오류

Python은 인터프리터 언어로 먼저 컴파일된 후 실행되지 않는다.정확히는 실행할 때마다 컴파일되므로 실행 시 코딩 오류가 나타난다. 이 모든 것이 결국 성능 저하, 시간 소비 및 많은 테스트의 필요성으로 이어진다. 특히 주피터 노트북에서 개발을 할 때 잦은 실수를 발생시킨다.

4. White space

Python에서는 white space는 다양한 코드 수준을 나타내기 위해 광범위하게 사용된다. 단, 중괄호와 세미콜론은 시각적으로 더 매력적이고, 초보자 친화적이며, 유지보수가 용이하며, 직관적으로 이해할 수 있다.

5. ㅍLambda

Python에서 lambda사용하는 것은 다소 제한적이기 때문에 문제가 있다. Python에서 lambda는 표현식일 뿐 statement가 될 수 없다.

6. 속도

Python은 동적 타입, 인터프리터 언어이므로 속도가 느리다. 곧 배포될 예정인 Python 3.11에서 성능 향상이 많이 된다고 한다. 그래도 느릴 수밖에 없다. 

7. 메모리

Python은 동적 타입 언어로, 어떤 변수로든 변할 수 있다. 하지만 그 만큼 많은 메모리를 차지하므로 메모리 낭비가 심하다.

8. 범위

Python은 동적 범위 지정과 관련이 있다. 모든 표현은 가능한 모든 컨텍스트에서 테스트해야 한다.

9. 정적 범위 설정 문제

동적 범위 지정으로 인해 발생하는 문제를 고려하여 파이썬은 정적 범위 지정으로 전환하려고 시도했지만 실패한 것 같다...

10. App development

크로스 플랫폼의 종류는 리엑티브 네이티브, 현재 주력으로 공부 중인 flutter, python으로 개발하는 kivy가 있다. 말도 아깝다. Kivy 맛보기 도전을 했는데, 바로 손절했다. 많이 사용하지 않는 데는 이유가 다 있다. 

728x90
반응형
반응형

Pyinstaller는 python 코드를 exe 파일로 변환하는 라이브러리이다.

사용법은 아래와 같다.

# main.py
from pyfiglet import Figlet


f = Figlet(font='slant')
print(f.renderText('Python'))

결과

# pyinstaller -w -F --icon {icon.ico} main.py

pyinstaller -F .\main.py
  • -w : 콘솔창 출력하지 않음
  • -F : 실행파일 하나만 생성
  • -icon : icon 모양

위 명령어를 실행하면 No module named 'pyfiglet.fonts' 오류가 발생하면서 콘솔창이 자동으로 종료된다.

오류를 해결하기 아래처럼 수행하면 해결된다.

pyinstaller --add-data " .\{Python 경로}\Lib\site-packages\pyfiglet;./pyfiglet" main.py

PyInstaller 명령 옵션에서 시스템의 Pyfiglet 폴더 경로를 제공하면 생성된 dist에 파일이 복사 된다.

728x90
반응형
반응형

네트워크를 통한 데이터를 가져오기, DB 쓰기 및 읽기, 파일 데이터 읽기 및 쓰기 등과 같은 경우 비동기 작업이 필요하다.

Future 란?
Future 클래스의 인스턴스이고, 비동기 작업의 결과를 나타내며 Uncompleted 또는 Completed의 두 가지 상태를 가질 수 있다.

Completed 상태는 작업이 완료된 상태이다. Uncompleted 상태는 작업이 완료되지 못한 상태이며, 완료할 작업은 event queue에 적재한다. 

Future는 보통 async, await와 함께 사용되며, 아래와 같이 사용한다.

  • async 함수를 정의하려면 함수 본문 앞에 async를 추가한다.
  • await 키워드는 비동기 함수에서만 작동한다.

1. Future, async, await
Future<void> printOrderMessage() async {
  print('Awaiting user order...');
  var order = await fetchUserOrder();
  print('Your order is: $order');
}

Future<String> fetchUserOrder() {
  // Imagine that this function is more complex and slow.
  return Future.delayed(const Duration(seconds: 4), () => 'Large Latte');
}

void main() async {
  countSeconds(4);
  await printOrderMessage();
}

void countSeconds(int s) {
  for (var i = 1; i <= s; i++) {
    Future.delayed(Duration(seconds: i), () => print(i));
  }
}
// Awaiting user order...
// 1
// 2
// 3
// 4
// Your order is: Large Latte
2. Error 다루기

비동기 함수에서 오류를 처리하려면 try-catch를 사용한다.

Future<void> printOrderMessage() async {
  try {
    print('Awaiting user order...');
    var order = await fetchUserOrder();
    print(order);
  } catch (err) {
    print('Caught error: $err');
  }
}

Future<String> fetchUserOrder() {
  // Imagine that this function is more complex.
  var str = Future.delayed(
      const Duration(seconds: 4),
      () => throw 'Cannot locate user order');
  return str;
}

void main() async {
  await printOrderMessage();
}
728x90
반응형

'Flutter > Dart' 카테고리의 다른 글

Dart Study #2 클래스, 상속  (0) 2022.08.04
Dart Study #1 기본 문법  (0) 2022.08.04

+ Recent posts