제3 장 펄 언어 (5) - 가방, 인용, 복잡 한 데이터
Perl 에 있 는 가방 은 단일 이름 공간 에 있 는 코드 집합 입 니 다.가방 과 이름 공간의 차 이 는 가방 의 관심 사 는 소스 코드 이다.이름 공간 은 Perl 이 코드 를 조직 하고 관리 하 는 내부 데이터 구조 이다.패키지 로 가방 과 이름 공간 을 설명 합 니 다. (가방 을 만 들 면 이름 공간 을 만 듭 니 다)
package MyCode;
our @boxes;
sub add_box { ... }
성명 후 다음 에 정 의 된 모든 변수 와 함 수 는 MyCode 의 이름 공간 에 있 습 니 다.이 패키지 성명 의 관할 범 위 는 다음 패키지 성명 을 만 나 거나 파일 이 끝 날 때 까지 지속 되 는 것 입 니 다.또한 블록 을 사용 하여 성명 범 위 를 지정 할 수 있 습 니 다.
package Pinball::Wizard
{
our $VERSION = 1969;
}
가방 설명 이 없 으 면 기본 값 은 main 가방 에 있 습 니 다.이전에 우 리 는 다른 가방 (이름 공간) 안의 변수 와 함 수 를 방문 하려 면 완전히 한 정 된 이름 을 사용 해 야 한다 고 말 한 적 이 있다.예 를 들 어 main 패키지 에서
@MyCode::boxes
를 사용 하여 MyCode 의 boxes 배열 을 방문 합 니 다.가방 에는 이름 외 에 버 전 번호 와 세 가지 함수 가 있 습 니 다. import (), unimport (), VERSION ().함수 VERSION () 은 가방 의 버 전 번호, 즉 가방 에 있 는 $VERSION 의 값 을 되 돌려 줍 니 다.Perl 은 버 전 번호 에 대해 격식 적 인 요구 가 있 습 니 다. 알파벳 v 로 시작 하고 최소 세 개 는 점 (.) 으로 정 수 를 구분 합 니 다.
package MyCode v1.2.1;
package Pinball::Wizard v1969.3.7 { ... }
# ,
package MyCode;
our $VERSION = 1.21;
모든 가방 은 UNIVERSAL 클래스 에서 VERSION () 함 수 를 계승 합 니 다.
my $version = Some::Plugin->VERSION;
# $VERSION
( ) , , :
# require at least 2.1
Some::Plugin->VERSION( 2.1 );
die "Your plugin $version is too old" unless $version > 2;
가방 과 이름 공간
컴 파일 기간 과 실행 시 가방 의 내용 을 어디서 든 방문 하거나 수정 할 수 있 지만 코드 를 읽 기 어 려 울 수 있 습 니 다.많은 항목 들 이 자신의 최상 위 이름 공간 을 만 듭 니 다. 그러면 전체 변수 충돌 가능성 을 줄 이 고 더 좋 은 조직 코드 도 만 들 수 있 습 니 다. 예 를 들 어:
• StrangeMonkey
• StrangeMonkey::UI
• StrangeMonkey::Persistence
• StrangeMonkey::Test
이것 은 약속 일 뿐 강제 적 인 것 은 아니 지만, 이런 약속 은 매우 통용 된다.
인용 하 다.
먼저 예 를 들 어:
sub reverse_greeting
{
my $name = reverse shift;
return "Hello, $name!";
}
my $name = 'Chuck';
say reverse_greeting( $name );
say $name;
우 리 는 하나의 함 수 를 통 해 반전 기능 을 실현 하 기 를 기대한다.그러나 예 에서 코드 는 이렇게 작 동 합 니 다. 변수 값 을 함수 에 전달 하고 함수 내부 에서 반전 합 니 다.그러나 완성 후 함수 가 나 왔 지만 변수 값 은 변 하지 않 았 습 니 다 (아니면 Chuck).
한 가지 상황 을 다시 고려 해 보 세 요. 한 가지 값 이 있 습 니 다. 다른 곳 에서 여러 부 를 복 사 했 습 니 다. 지금 이 값 을 수정 해 야 합 니 다. 그러면 모든 곳 에서 고 치 려 고 합 니까?한 가지 수정 을 실현 할 수 있 는 메커니즘 이 있 습 니까?네, 인용 에 쓰 겠 습 니 다.
스칼라 참조
역 슬 래 쉬 를 사용 하여 인용 을 만 듭 니 다.스칼라 언어 환경 에서 하나의 인용 을 만 듭 니 다.목록 언어 환경 에서 일련의 인용 을 만 듭 니 다.인용 에 기호 ($) 를 추가 하면 인용 한 값 에 접근 할 수 있 습 니 다. 이것 이 바로 인용 을 푸 는 것 입 니 다.
my $name = 'Larry';
my $name_ref = \$name;
#
say $$name_ref;
위의 반전 예 를 인용 으로 구현 합 니 다.
sub reverse_in_place
{
my $name_ref = shift;
$$name_ref = reverse $$name_ref; #
}
my $name = 'Blabby';
reverse_in_place( \$name );
say $name;
매개 변수
@_
는 매개 변수 변수의 별명 이기 때문에 똑 같은 효 과 를 실현 할 수 있 습 니 다.sub reverse_value_in_place
{
$_[0] = reverse $_[0];
}
my $name = 'allizocohC';
reverse_value_in_place( $name );
say $name;
#
함수 전달 인용 을 호출 하면 메모리 사용 을 줄 일 수 있 습 니 다.이것 은 이해 하기 쉽 습 니 다. 다음 에 전달 하 는 큰 문자열 을 매개 변수 로 하고 전달 문자열 의 인용 을 비교 합 니 다.
복잡 한 인용 은 괄호 로 나 쁜 의 미 를 없 애 야 할 수도 있 습 니 다. 이것 이 야 말로 완전한 문법 입 니 다. 다만 대부분 생략 했 을 뿐 입 니 다.
sub reverse_in_place
{
my $name_ref = shift;
${ $name_ref } = reverse ${ $name_ref };
}
사용 할 때 인용 을 알 아 보 는 것 을 잊 어 버 리 면 펄 은 언어 환경 에 따라 문자열 SCALAR (0x93339e 8) 또는 숫자 0x93339e 8 로 강제로 변환 합 니 다.(그러나 이것 은 반드시 변수의 실제 메모리 주소 가 아 닙 니 다.
배열 참조
배열 참조 에는 다음 과 같은 용도 가 있 습 니 다.
my @cards = qw( K Q J 10 9 8 7 6 5 4 3 2 A );
my $cards_ref = \@cards;
$cards ref 를 참조 하여 수정 하면 배열 @ cards 를 직접 수정 합 니 다. 기호 @ 을 사용 하여 인용 을 풀 고 전체 배열 에 접근 할 수 있 습 니 다.
my $card_count = @$cards_ref;
my @card_copy = @$cards_ref;
화살표 기호 (- >) 를 사용 하여 단일 요소 에 접근 하기:
my $first_card = $cards_ref->[0];
my $last_card = $cards_ref->[-1];
이렇게 방문 할 수도 있 습 니 다.
my $first_-card = $$cards_ref[0];
# !
슬라이스:
my @high_cards = @{ $cards_ref }[0 .. 2, -1];
# ,
익명 배열, 참조 로 만 접근 할 수 있 습 니 다.
my $suits_ref = [qw( Monkeys Robots Dinos Cheese )];
다음 두 가지 상황 구분:
#
my @meals = qw( soup sandwiches pizza );
my $sunday_ref = \@meals;
my $monday_ref = \@meals;
my @meals = qw( soup sandwiches pizza );
my $sunday_ref = [ @meals ];
my $monday_ref = [ @meals ];
# 2 @meals , 。
해시 인용
해시 참조 만 들 기:
my %colors = (
blue => 'azul',
gold => 'dorado',
red => 'rojo',
yellow => 'amarillo',
purple => 'morado',
);
my $colors_ref = \%colors;
인용 하기 전에 기호% 를 사용 하여 전체 해시 에 접근 하고 사용 합 니 다:
my @english_colors = keys %$colors_ref;
my @spanish_colors = values %$colors_ref;
화살표 연산 자 (- >) 를 사용 하여 요소 에 접근 하기:
sub translate_to_spanish
{
my $color = shift;
return $colors_ref->{$color};
# or return $$colors_ref{$color};
}
슬라이스:
my @colors = qw( red blue green );
my @colores = @{ $colors_ref }{@colors};
괄호 로 익명 해시 만 들 기:
my $food_ref = {
'birthday cake' => 'la torta de cumpleaños',
candy => 'dulces',
cupcake => 'bizcochito',
'ice cream' => 'helado',
};
함수 참조
함수 이름 에 대해 서 는 인용 연산 자 와 & 기 호 를 사용 하여 함수 인용 을 만 듭 니 다.
sub bake_cake { say 'Baking a wonderful cake!' };
my $cake_ref = \&bake_cake;
# & , & , 。
키워드 sub 를 사용 하여 익명 함수 만 들 기:
my $pie_ref = sub { say 'Making a delicious pie!' };
인용 호출 함수:
$cake_ref->();
$pie_ref->();
파일 핸들 참조
open 과 opendir 연산 자 에서 품사 변 수 를 사용 할 때 이 변 수 는 파일 핸들 참조 입 니 다. 이 핸들 은 IO: File 대상 입 니 다. 대상 방법 을 직접 호출 할 수 있 습 니 다.
use autodie 'open';
open my $out_fh, '>', 'output_file.txt';
$out_fh->say( 'Have some text!' );
오래된 코드 는 IO:: Handle 대상 을 사용 할 수 있 고 더 오래된 코드 는 기호 참조 를 사용 할 수 있 습 니 다.
local *FH;
open FH, "> $file" or die "Can't write '$file': $!";
my $fh = \*FH;
이러한 방식 은 여전히 사용 할 수 있 지만, 우 리 는 최신 품사 변수 방식 을 건의 합 니 다.
인용 계수
Perl 은 인용 계수 방식 으로 메모 리 를 관리 합 니 다. 모든 Perl 변 수 는 하나의 카운터 가 있 습 니 다. 인용 을 추가 하면 Perl 은 계산 기 를 하나 더 하고 인용 을 줄 이면 하 나 를 줄 입 니 다. 카운터 가 0 일 때 Perl 은 이 변 수 를 안전하게 회수 할 수 있다 고 생각 합 니 다.
다음 코드 고려:
say 'file not open';
{
open my $fh, '>', 'inner_scope.txt';
$fh->say( 'file open here' );
}
say 'file closed here';
변수 $fh 의 역할 영역 은 블록 안에 있 습 니 다. 범 위 를 초과 할 때 변수 가 효력 을 잃 습 니 다. Perl 은 계산 을 하나 줄 이 고 0 으로 바 꾸 면 Perl 은 해당 하 는 메모 리 를 회수 합 니 다. 모든 기술 세부 사항 을 알 필요 가 없습니다. 인용 을 사용 할 때 Perl 의 메모리 관리 에 어떻게 영향 을 미 치 는 지 알 면 됩 니 다.
인용 과 함수
함수 에 인용 을 전달 할 때 조심해 야 합 니 다. 함수 에서 원래 의 값 을 수정 할 수 있 습 니 다. 이것 은 당신 이 원 하 는 것 이 아 닐 수도 있 습 니 다. 이 상황 을 피 하려 면 먼저 변수 값 을 새로운 변수 로 복사 해 야 합 니 다.
my @new_array = @{ $array_ref };
my %new_hash = %{ $hash_ref };
# , Storable dclone() 。
내장 형 데이터 구조
때때로 당신 은 다 차원 배열 을 만 들 고 싶 지만 다음 과 같은 방식 으로 원 하 는 것 을 얻 을 수 없습니다.
my @counts = qw( eenie miney moe );
my @ducks = qw( huey dewey louie );
my @game = qw( duck duck goose );
my @famous_triplets = (
@counts, @ducks, @game
);
이것 은 모든 데 이 터 를 하나의 목록 으로 합 쳐 하나의 배열 에 값 을 부여 합 니 다. 다 차원 배열 이 아 닙 니 다.
해결 방법 은 인용 이다.
#
my @famous_triplets = (
\@counts, \@ducks, \@game
);
# :
my @famous_triplets = (
[qw( eenie miney moe )],
[qw( huey dewey louie )],
[qw( duck duck goose )],
);
#
my %meals = (
breakfast => { entree => 'eggs',
side => 'hash browns' },
lunch => { entree => 'panini',
side => 'apple' },
dinner => { entree => 'steak',
side => 'avocado salad' },
);
마지막 요소 항목 뒤의 쉼표 는 선택 할 수 있 습 니 다. 게다가 원 소 를 추가 하 는 것 이 편리 합 니 다.
인용 접근 다 차원 데이터 구 조 를 사용 하면 화살 표 는 선택 할 수 있 습 니 다.
#
my $nephew = $famous_triplets[1][2];
my $meal = $meals{breakfast}{side};
#
my $last_nephew = $famous_triplets[1]->[2];
my $meal_side = $meals{breakfast}->{side};
# :
$actions{generous}{buy_food}->( $nephew, $meal );
포 함 된 데이터 구조의 내용 이 배열 과 해시 라면 괄호 를 통 해 가 독성 을 증가 합 니 다.
my $nephew_count = @{ $famous_triplets[1] };
my $dinner_courses = keys %{ $meals{dinner} };
포 함 된 데이터 의 절편:
my ($entree, $side) =
@{ $meals{breakfast} }{ qw( entree side ) };
:
my $meal_ref = $meals{breakfast};
my ($entree, $side) = @$meal_ref{qw( entree side )};
my ($entree, $side) = @{ $_ }{qw( entree side )}
for $meals{breakfast};
perldoc perldsc 는 Perl 의 각종 데이터 구조의 사용 예 를 볼 수 있 습 니 다.
자동 활성화
포 함 된 데이터 구조의 일부분 을 쓸 때 Perl 은 중간 에 필요 한 과정 을 자동 으로 만 듭 니 다.
my @aoaoaoa;
$aoaoaoa[0][0][0][0] = 'nested deeply';
Perl 은 이 4 차원 배열 을 자동 으로 만 듭 니 다. 각 배열 은 하나의 요 소 를 포함 하고 있 습 니 다. 유사 한 것 은 다음 절 에서 해시 의 하 시 를 자동 으로 만 듭 니 다.
my %hohoh;
$hohoh{Robot}{Santa} = 'mostly harmful';
이 동작 을 자동 활성화 라 고 합 니 다. 편리 하지만 본의 아니 게 당신 의 의 도 를 오해 할 수도 있 습 니 다. (당신 이 잘못 썼 습 니 다) CPAN 에 autovification 의 컴 파일 명령 이 있 습 니 다. 이 기능 의 사용 과 범 위 를 제어 할 수 있 습 니 다.
디버그 내장 데이터 구조
모듈 Data: Dumper 는 데이터 구 조 를 표시 할 수 있 습 니 다.
use Data::Dumper;
my $complex_structure = {
numbers => [ 1 .. 3 ];
letters => [ 'a' .. 'c' ],
objects => {
breakfast => $continental,
lunch => $late_tea,
dinner => $banquet,
},
};
print Dumper( $complex_structure );
$VAR1 = {
'numbers' => [
1,
2,
3
],
'letters' => [
'a',
'b',
'c'
],
'meals' => {
'dinner' => bless({...}, 'Dinner'),
'lunch' => bless({...}, 'Lunch'),
'breakfast' => bless({...}, 'Breakfast'),
},
};
물론 다른 모듈 도 이 일 을 할 수 있 습 니 다. YAML: XS 와 JSON 모듈 입 니 다. 개발 자 들 은 이 2 모듈 을 사용 하 는 경향 이 있 을 수 있 습 니 다. 이 2 모듈 은 Perl 코드 가 생기 지 않 고 출력 결과 가 더욱 뚜렷 합 니 다. Data: Dumper 는 매우 상세 하 게 표 시 됩 니 다.
회로 참조
회로 참조 (상호 참조) 가 존재 할 때 인용 기록 기 는 0 이 될 수 없고 Perl 도 메모 리 를 영원히 회수 할 수 없습니다.
my $alice = { mother => '', father => '' };
my $robin = { mother => '', father => '' };
my $cianne = { mother => $alice, father => $robin };
push @{ $alice->{children} }, $cianne;
push @{ $robin->{children} }, $cianne;
Scalar:: Util 's 의 weaken () 함수 (약 인용) 를 사용 할 수 있 습 니 다. 약 인용 을 사용 하면 인용 수 를 증가 하지 않 습 니 다.
use Scalar::Util 'weaken';
my $alice = { mother => '', father => '' };
my $robin = { mother => '', father => '' };
my $cianne = { mother => $alice, father => $robin };
push @{ $alice->{children} }, $cianne;
push @{ $robin->{children} }, $cianne;
weaken( $cianne->{mother} );
weaken( $cianne->{father} );
물론 대부분의 정상 적 인 데이터 구 조 는 회로 인용 이 나타 나 지 않 고 약 한 인용 을 사용 할 필요 가 없다.
대체 내장 데이터 구조
Perl 에 게 는 상관 없습니다. 아무리 복잡 한 내장 데이터 결과 도 순조롭게 처리 할 수 있 지만 사람 이 안 됩 니 다. 2 층 이나 3 층 이 넘 으 면 이해 하기 어렵 습 니 다. 이 럴 때 는 클래스 와 대상 기술 을 사용 하여 코드 를 더욱 선명 하 게 하 는 것 을 고려 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.